Как работать с несколькими вариантами чтения в reactjs

#reactjs #react-hooks #use-state

#reactjs #реагирующие хуки #use-state

Вопрос:

У меня есть для категорий с полями изображения и описания. каждое описание содержит большой текст, если он превышает 200 слов, тогда должна отображаться read more ссылка. При нажатии на подробнее там также должен отображаться полный текст со readless ссылкой. Я попробовал приведенный ниже код, но если я нажму на 1-ю подкатегорию, откроется enter code here ссылка на все категории для чтения. если я нажму readless, это сработает для всех других категорий readless link. Как сделать каждую работу отдельной с помощью ссылок readmore и readless.

Вот мой код

У меня есть для категорий с полями изображения и описания. каждое описание содержит большой текст, если он превышает 200 слов, тогда должна отображаться read more ссылка. При нажатии на подробнее там также должен отображаться полный текст со readless ссылкой. Я попробовал приведенный ниже код, но если я нажму на 1-ю подкатегорию, откроется enter code here ссылка на все категории для чтения. если я нажму readless, это сработает для всех других категорий readless link. Как сделать каждую работу отдельной с помощью ссылок readmore и readless.

Вот мой код

      import React,{useState} from 'react';
    
    export function FullReport(props) {
      const [readMore, setReadMore] = React.useState(false);
      const linkName = readMore ? "...Read Less" : "...Read More";
      const [categories, setcategories] = React.useState([]);
       
      React.useEffect(() => {
          try {
            axios
              .get(
                `/getReportDetails`
              )
              .then(
                (response) => {
                  console.log(response);
                  let serverData = response.data.data;
                  let categories = [];
                  serverData.categoryDetails.forEach((data) => {
                    categories.push(data);
                  });
                  setcategories(categories);
                },
              
              );
      
          } catch (e) {
          }
        }, [categories.length);
      
    return (
    <div>
        {categories.map((sitems, ssindex) => {
        <p>{sitems.name}</p>
        <p>
          {!readMore amp;amp;
            sitems?.description?.substring(
              0,
              201
            )}
          {readMore amp;amp; sitems?.description}
          <Link
            to="#"
            className="read-more-link"
            onClick={() => {
              setReadMore(!readMore);
            }}
          >
            <>
              {sitems?.description?.length >
                201 amp;amp; linkName}
            </>
          </Link>
        </p>
        }
   </div>
  )};
 

Комментарии:

1. Вы хотите открывать какой-либо один read more за раз или несколько вариантов чтения??

2. Я должен открывать по одному чтению за раз.

Ответ №1:

Я создал пример. Вы можете обратиться к этой ссылке на код

одновременно открывается несколько руд для чтения

Песочница: https://codesandbox.io/s/happy-swartz-ikqdn?file=/src/read-multi.js

Note: перейдите к /read-multi codesandbox Browser


за один раз открывается руда для чтения

Песочница: https://codesandbox.io/s/happy-swartz-ikqdn?file=/src/read-single.js

Note: перейдите к /read-single codesandbox Browser


Что вы делаете, так это сохраняете одно состояние для чтения большего количества всех категорий.

для множественного чтения

У вас должно быть отдельное состояние для каждой категории, и вы должны переключать это состояние только при нажатии кнопки readmore определенной категории. Для отдельного состояния чтения я взял логическое состояние массива размера категорий.


для однократного чтения

У вас должен быть readState index открытый в данный момент, и если вы хотите открыть любой другой, затем сбросьте индекс readMore на новый индекс. в противном случае установите его равным -1, чтобы ничего не открывалось.

Комментарии:

1. @ Химаншу Сингх, у меня есть поле описания для каждой категории. Поэтому, если длина описания больше 201, я должен показать ссылку «Подробнее». Мой pblm заключается в том, что если я нажму любую ссылку для чтения в любом описании, откроется все остальные дополнительные сведения. И если я нажму меньше читать, все меньше читать будет работать.

2. Попробуйте это, вам нужно сохранить текущий открытый индекс, а не true или false. Если current iterated category's index === current open index , то он покажет все описание, в противном случае нет.

3. прочитайте описание и просмотрите код, вы можете легко понять.

4. вы можете пометить это как ответ и закрыть вопрос

Ответ №2:

Вы должны проверять индекс и управлять состояниями с помощью своего индекса вместо использования одного логического значения. Вы должны легко исправить это с помощью состояний объекта, например const [readMore, setReadMore] = React.useState({isOpen: false, index: 0});

Но вместо реализации этого решения я бы создал новый компонент для этой части

         <p>{sitems.name}</p>
        <p>
          {!readMore amp;amp;
            sitems?.description?.substring(
              0,
              201
            )}
          {readMore amp;amp; sitems?.description}
          <Link
            to="#"
            className="read-more-link"
            onClick={() => {
              setReadMore(!readMore);
            }}
          >
            <>
              {sitems?.description?.length >
                201 amp;amp; linkName}
            </>
          </Link>
        </p>
 

и верните его в функции map. Вы должны поместить свое состояние внутри нового компонента вместо использования внутри FullReport компонента, и вы можете использовать его как логическое значение, как вы используете сейчас

 const [readMore, setReadMore] = React.useState(false);
 

@Evren, согласно вашему предложению, мой отредактированный код находится здесь, разделенный на 2 компонента. но ссылки readmore не работают при нажатии сейчас.Пожалуйста, помогите мне исправить ошибку.

 import React,{useState} from 'react';

export function FullReport(props) {
  const [categories, setcategories] = React.useState([]);
   
  React.useEffect(() => {
      try {
        axios
          .get(
            `/getReportDetails`
          )
          .then(
            (response) => {
              console.log(response);
              let serverData = response.data.data;
              let categories = [];
              serverData.categoryDetails.forEach((data) => {
                categories.push(data);
              });
              setcategories(categories);
            },
          
          );
  
      } catch (e) {
      }
    }, [categories.length);
  



  const ProfileItem = (sitems) => {
      const [readMore, setReadMore] = React.useState(false);
      return (
              <div>
                <p>
                  {!readMore amp;amp;
                    sitems?.description?.substring(
                      0,
                      201
                    )}
                  {readMore amp;amp; sitems?.description}
                    <Link to="#" className="read-more-link" onClick={() => setReadMore(!readMore);
                                        }}>
                  {readMore ? "Read Less" : "Read more"}
                </Link>
                </p>
              </div>
            )}
                                   


      return (
          <div>
              {categories.map((sitems, ssindex) => {
                  <ProfileItem {...sitems} />
            })}
           </div>        
            );
          };
 

Я создал для вас рабочий пример. При рефакторинге вы не создавали новый компонент, вы просто создали функцию внутри компонента react. Здесь изолированная среда кода и код

 import React  from 'react';

export default function App(props) {
  const categories = [{description:'123456789'},
                      {description:'123456789'},
                      {description:'123456789'},
                      {description:'123456789'}]
   
      return (
          <div>
              {categories?.map((sitems, ssindex) => {
                return  <ProfileItem  sitems={sitems} />
                   
            })} 
           </div>        
            );
          };
export const ProfileItem = ({sitems}) => {
          const [readMore, setReadMore] = React.useState(false);
          return (
                  <div style={{border:'1px solid black', width: 300}} onClick={()=>setReadMore(!readMore)}>
                    <p  >
                    {!readMore amp;amp;
                    sitems?.description?.substring(
                      0,
                      5
                    )}
                  {readMore amp;amp; sitems?.description} 
                    </p>
                  </div>
                )}
 

https://codesandbox.io/s/strange-sound-j93lv?file=/src/App.js

Комментарии:

1. Согласно вашему предложению, я отредактировал приведенный выше код, создав 2 компонента. но теперь при нажатии readmore buton не работает. можете ли вы сказать, где я ошибся?

2. Я обновил свой ответ @SreRoR