#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. спасибо тебе, братан, за твои усилия помочь мне!