Не удалось сохранить данные в состоянии в react js

#javascript #reactjs

Вопрос:

У меня есть два данных в cardTypeData :

 0: {id: 226, obj: {…}, Slug: 'hello-0'
1: {id: 228, obj: {…}, Slug: 'hello-1'}
 

 useEffect(() => {
      let newcard = [];
      console.log("cardTypeData= ",cardTypeData)
          if (cardTypeData) {
            cardTypeData.map((item) => {
              if(item.Slug){
              const requestUrl = `chartconfig/${item.Slug}/${
                searchQuery?.year
                  ? `?year=${searchQuery.year}${
                      searchQuery.month ? "amp;month="   searchQuery.month : ""
                    }`
                  : ``
              }`;
              axiosRequest.get(requestUrl)
              .then((res) => {
                  newcard.push(res.data);
              })
              .catch(console.log('err'))
              // .catch((error)=>{
              //   console.log(error)
              // });
            }
            });
          }
          console.log('list', newcard)
          setCardData(newcard);
      }, [cardTypeData]);
 

вывод консоли показан на рисунке,
как устранить эту проблему.
введите описание изображения здесь

введите описание изображения здесь

здесь показаны данные, но я не смог отобразить их в html.

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

1. Пожалуйста, отформатируйте свой код и включите также метод визуализации.

Ответ №1:

Рефакторинг, рефакторинг и еще раз рефакторинг. Вышеперечисленные решения в целом работают так, как ожидалось, но могли бы быть написаны лучше. Надеюсь, вы не возражаете, если я покажу вам, как это должно выглядеть.

 function loadNewCards() {
  if (!cardTypeData) return

  cardTypeData.forEach(async (cardItem) => {
    if (!cardItem.Slug) return

    const searchParams = new URLSearchParams(searchQuery).toString()
    const requestUrl = `chartconfig/${cardItem.Slug}/${searchParams}`
    const response = await axios.get(requestUrl).catch(console.log)

    if (!response) return

    setCardData(prevCardData => [...prevCardData, response.data])
  })
}

useEffect(() => {
  loadNewCards()
}, [cardTypeData])
 

Во-первых, пожалуйста, избегайте вложенности. Это делает ваш код менее читабельным.
Попробуйте использовать отрицание, чтобы избежать вложенного оператора if / else.

 if (!cardItem.Slug) return
 

было бы лучше, чем

 if (item.Slug) {
   const requestUrl = `chartconfig/${item.Slug}`
 

Во — вторых, пожалуйста, используйте URLSearchParams для построения параметров запроса.
Этот класс будет обрабатывать ваш объект, содержащий year и month .
Я думаю, что лучше иметь

 const searchParams = new URLSearchParams(searchQuery).toString()
const requestUrl = `chartconfig/${cardItem.Slug}/${searchParams}`
 

вместо

 const requestUrl = `chartconfig/${item.Slug}/${
  searchQuery?.year
    ? `?year=${searchQuery.year}${
      searchQuery.month ? 'amp;month='   searchQuery.month : ''
    }`
    : ``
}`
 

Ответ №2:

Сетевой запрос является асинхронным. Перед newcard.push(res.data) запуском setCardData(newcard) уже выполняется с инициализированным значением newcard, которое равно [ ], …вы можете изменить код примерно так, как показано ниже, чтобы он работал

 useEffect(() => {
      // let newcard = [];
      console.log("cardTypeData= ",cardTypeData)
          if (cardTypeData) {
            cardTypeData.map((item) => {
              if(item.Slug){
              const requestUrl = `chartconfig/${item.Slug}/${
                searchQuery?.year
                  ? `?year=${searchQuery.year}${
                      searchQuery.month ? "amp;month="   searchQuery.month : ""
                    }`
                  : ``
              }`;
              axiosRequest.get(requestUrl)
              .then((res) => {
                   
                  ***** modified 👇*****
                  // newcard.push(res.data);
                  setCardData(prev => [...prev, res.data])
              })
              .catch(console.log('err'))
              // .catch((error)=>{
              //   console.log(error)
              // });
            }
            });
          }
          console.log('list', newcard)
          // setCardData(newcard);
      }, [cardTypeData]);
 

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

1. Большое тебе спасибо, брат. Это сработало идеально

2. я рад, что это помогло.

3. при переходе на следующую страницу с этой страницы и возвращении обратно появляется больше данных, я имею в виду, что при возвращении на эту страницу я получаю двойные данные .

Ответ №3:

Я где-то читал об этой консоли.журнал не всегда запускается в точное время, когда вы его вызываете, иногда он немного ждет, особенно когда вы расширяете ввод.

Проблема может быть связана с вызовами api из cardTypeData.map.

Попробуйте вместо этого использовать for, чтобы проверить это. Кроме того, вам придется извлечь асинхронную часть, потому что React не любит асинхронный эффект использования..

Что-то вроде этого:

 const loadNewCards = async () => {
let newcard = [];
console.log("cardTypeData= ", cardTypeData);
if (cardTypeData) {
    for (let item of cardTypeData) {
  if (!item.Slug) {
    const requestUrl = `chartconfig/${item.Slug}/${
      searchQuery?.year
        ? `?year=${searchQuery.year}${
            searchQuery.month ? "amp;month="   searchQuery.month : ""
          }`
        : ``
    }`;
    await axiosRequest
      .get(requestUrl)
      .then((res) => {
        newcard.push(res.data);
      })
      .catch(console.log("err"));
  }
}
}
console.log("list", newcard);
setCardData(newcard);
};
useEffect(() => {
    loadNewCards();
}, [cardTypeData]);
 

И если вы беспокоитесь о производительности, вам следует использовать Promise.all для параллельного выполнения всех вызовов.

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

1. спасибо тебе, братан, за твои усилия помочь мне!