useState передавать асинхронно с useEffect
Есть функция которая перебирает url как массив, и мне нужно перенести эти urls в другой fetch запрос. И тут возникла проблема, что хук не отрабатывает с первого раза. url2 это то, что я хочу передать
//Функция работает по клику
let getDataCategory = async (event) => {
let id = event.currentTarget.id;
await fetch(`http://api.tmweb.ru/category?filter[parent_id][in]=${id}&filter[type]=0`,{
headers: {
'Accept': 'application/json',
'Authorization': token,
},
})
.then(res => res.json())
.then((result) => {
setCategoryUrl(result.data)
setCategorySub([...categorySub,...result.data]);
let url2 = `http://api.tmweb.ru/object?filter[category_id][in][]=${id}&`
result.data.forEach(item => {url2 += 'filter[category_id][in][]=' + item.id + '&'})
setCategoryUrl(url2) // Вот это нужно передать
});
// Cюда передаю, url генерируется правильно, но генерируется не с первого клика
await fetch(`${categoryUrl}&filter[type]=0`,{
headers: {
'Accept': 'application/json',
'Authorization': token,
},
})
}
Пробовал useEffect, но он тоже не особо помог. Отрабатывается всё с задержкой.
useEffect(()=>{
console.log(categoryUrl)
}, [categoryUrl])
Тут полный код кому интересно
//Это категории по которым кликаю
useEffect(() => {
fetch('http://api.tmweb.ru/category?filter[depth]=1&filter[type]=0',{
headers: {
'Accept': 'application/json',
'Authorization': token,
}
})
.then(res => res.json())
.then((result) => setCategory(result.data),
)
}, [])
useEffect(()=>{
console.log(categoryUrl)
}, [categoryUrl])
//Клик по категориям
let getDataCategory = async (event) => {
let id = event.currentTarget.id;
//Проверка чекбокса
if (event.target.checked){
await fetch(`http://api.tmweb.ru/category?filter[parent_id][in]=${id}&filter[type]=0`,{
headers: {
'Accept': 'application/json',
'Authorization': token,
},
})
.then(res => res.json())
.then((result) => {
//Тут подкатегории и выбор url
setCategoryUrl(result.data)
setCategorySub([...categorySub,...result.data]);
let url2 = `http://api.tmweb.ru/object?filter[category_id][in][]=${id}&`
result.data.forEach(item => {url2 += 'filter[category_id][in][]=' + item.id + '&'})
setCategoryUrl(url2)
});
//Тут должны выводиться подкатегории
await fetch(`${categoryUrl}&filter[type]=0`,{
headers: {
'Accept': 'application/json',
'Authorization': token,
},
})
.then(res => res.json())
.then((result) => {
console.log(result)
setCategoryProd([...categoryProd,...result.data])
})
//Удаление элементов
}else {
// Удаляете элемент из состояния
setCategorySub((prevData) => { //prevData текущее состояние
return prevData.filter((item) => item.parent_id !== +id);
});
setCategoryProd((prevData) =>{
return prevData.filter((item) => item.category_id !== +id);
})
}
}
Ответы (2 шт):
Передаем асинхронно данные для обработки в функциональном компоненте React
Вариант #1 - Используем цепочку промисов then() для передачи данных
let getDataCategory = async (event) => {
let id = event.currentTarget.id;
//Проверка чекбокса
if (event.target.checked) {
await fetch(`http://api.tmweb.ru/category?filter[parent_id][in]=${id}&filter[type]=0`, {
headers: {
'Accept': 'application/json',
'Authorization': token,
},
})
.then(res => res.json())
.then((result) => {
//Тут подкатегории и выбор url
setCategorySub([...categorySub, ...result.data]);
let url2 = `http://api.tmweb.ru/object?filter[category_id][in][]=${id}&`
result.data.forEach(item => {
url2 += 'filter[category_id][in][]=' + item.id + '&'
})
setCategoryUrl(url2)
return url2; // Передаем url дальше, не дожидаясь изменения состояния компонента
})
.then(url =>
// выполняем необходимый запрос и отправляем данные для сохранения в состоянии компонента
fetch(`${url}&filter[type]=0`, {
headers: {
'Accept': 'application/json',
'Authorization': token,
},
})
.then(res => res.json())
.then((result) => setCategoryProd([...categoryProd, ...result.data]))
);
//Удаление элементов
} else {
// Удаляете элемент из состояния
setCategorySub((prevData) => { //prevData текущее состояние
return prevData.filter((item) => item.parent_id !== +id);
});
setCategoryProd((prevData) => {
return prevData.filter((item) => item.category_id !== +id);
})
}
}
Вариант №2 - Используем хук useEffect функционального компонента React для того что бы при изменении состояния переменной categoryUrl произвести новый запрос для выборки данных с новыми параметрами.
useEffect - отслеживает изменение переменных функционально компонента и выполняет код, указанный в callBack функции каждый раз, когда переменная из указанных в зависимостях изменилась.
Общий вид хука
useEffect(() => { code }, [dep1, dep2, depN]);
useEffect(() => { // делаем асинхронной функцию
// Выполняем fetch запрос с обновленным значением categoryUrl
fetch(`${categoryUrl}&filter[type]=0`, {
headers: {
'Accept': 'application/json',
'Authorization': token,
},
})
.then(res => res.json())
.then((result) => setCategoryProd([...categoryProd, ...result.data]))
}, [categoryUrl]) // Будет срабатывать при каждом изменении categoryUrl
//Клик по категориям
let getDataCategory = async (event) => {
let id = event.currentTarget.id;
//Проверка чекбокса
if (event.target.checked) {
await fetch(`http://api.tmweb.ru/category?filter[parent_id][in]=${id}&filter[type]=0`, {
headers: {
'Accept': 'application/json',
'Authorization': token,
},
})
.then(res => res.json())
.then((result) => {
//Тут подкатегории и выбор url
setCategorySub([...categorySub, ...result.data]);
let url2 = `http://api.tmweb.ru/object?filter[category_id][in][]=${id}&`
result.data.forEach(item => {
url2 += 'filter[category_id][in][]=' + item.id + '&'
})
setCategoryUrl(url2)
return url2;
});
//Удаление элементов
} else {
// Удаляете элемент из состояния
setCategorySub((prevData) => { //prevData текущее состояние
return prevData.filter((item) => item.parent_id !== +id);
});
setCategoryProd((prevData) => {
return prevData.filter((item) => item.category_id !== +id);
})
}
}
Нашёл ещё один вариант через переменную.
let getDataCategory = async (event) => {
let id = event.currentTarget.id;
let newUrl = ''; // Создаем новую переменную
if (event.target.checked){
await fetch(`http://api.tmweb.ru/category?filter[parent_id][in]=${id}&filter[type]=0`,{
headers: {
'Accept': 'application/json',
'Authorization': token,
},
})
.then(res => res.json())
.then((result) => {
setCategorySub([...categorySub,...result.data]);
let url2 = `http://api.tmweb.ru/object?filter[category_id][in][]=${id}&`
result.data.forEach(item => {url2 += 'filter[category_id][in][]=' + item.id + '&'})
newUrl = url2; //присваиваем новое значение
});
await fetch(`${newUrl}&filter[type]=0`,{
headers: {
'Accept': 'application/json',
'Authorization': token,
},
})