Как выводить запросы пока не будет получен нормальный ответ с сервера
у меня есть компонент App в котором выполняются функции getStore и getProduct
import { useDispatch, useSelector } from 'react-redux';
import ProductCard from './components/ProductCard';
import Container from 'react-bootstrap/Container';
import { AsideMenu } from './components/AsideMenu';
import { useEffect, useState } from 'react';
import { getStore, getProduct } from './http/productStore';
import Pagination from './components/Pagination';
import './App.css'
function App() {
const ids = useSelector(state => state.idList)
const products = useSelector(state => state.productsList)
const dispatch = useDispatch()
useEffect(() => {
getStore().then(res => dispatch({ type: 'SET_ID', ids: Array.from(new Set(res.result)) }))
}, []);
console.log(ids, products)
// Пагинация
const [currentPage, setCurrentPage] = useState(1)
const [productPerPage] = useState(50)
const lastIdIndex = currentPage * productPerPage
const firstProductIndex = lastIdIndex - productPerPage
const currentIds = ids.slice(firstProductIndex, lastIdIndex)
getProduct(currentIds).then(res => dispatch({ type: 'SET_LIST', products: res.result }))
const paginate = pageNumber => setCurrentPage(pageNumber)
return (
<Container className='body'>
<div className='header'>
<h1 className='title'>Valantis</h1>
</div>
<Container className='section'>
<Container className='product-block'>
{products.map(product => <ProductCard id={product.id} name={product.product} price={product.price} brand={product.brand}></ProductCard>)}
</Container>
<Container className='aside-block'>
<AsideMenu name='цене'></AsideMenu>
<AsideMenu name='названию'></AsideMenu>
<AsideMenu name='бренду'></AsideMenu>
<AsideMenu name='идентификатору'></AsideMenu>
</Container>
<Pagination productPerPage={productPerPage} totalProducts={ids.length} paginate={paginate}></Pagination>
</Container>
</Container>
);
}
export default App;
getProduct может нормально выполниться только при условии полученного с сервера массива, но проблема в том что даже если запрос успешно получен, то за время пока он придёт с сервера, getProduct уже выполниться просто так один раз, если я её засуну в useEffect, если без него функция начинает повторяться бесконечно раз что пусть и даёт вывести данные но очень плохо влияет на север. Возник вопрос, как повторять getProduct или задержать его пока не придёт полноценный ответ с сервера.
вот файл с функциями
import CryptoJS from 'crypto-js';
const password = 'Valantis';
const timestamp = new Date().toISOString().slice(0, 10).split('-').join('');
const data = `${password}_${timestamp}`;
const authorizationString = CryptoJS.MD5(data).toString();;
export async function getStore() {
const res = await fetch("http://api.valantis.store:40000/", {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Auth': authorizationString
},
body: JSON.stringify(
{
action: 'get_ids'
}
),
}).then(response => { return response }).catch(err => {
getStore()
alert(err)
});
return res.json()
}
export async function getProduct(ids) {
const items = await fetch("http://api.valantis.store:40000/", {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Auth': authorizationString
},
body: JSON.stringify(
{
action: "get_items",
params: { "ids": ids }
}
),
}).then(response => { return response }).catch(err => {
alert(err)
getProduct(ids)
})
getProduct(ids)
return items.json()
}
export async function getFilterProduct(filter) {
const filterItems = await fetch("http://api.valantis.store:40000/", {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Auth': authorizationString
},
body: JSON.stringify(
{
"action": "filter",
"params": { price: filter }
}
),
}).then(response => { return response }).catch(err => alert(err))
return filterItems.json()
}
Ответы (1 шт):
Положите вызов функции в useEffect с нужной зависимостью
useEffect(() => {
getProduct(currentIds).then(res => dispatch({ type: 'SET_LIST', products: res.result }));
}, [ids]);
Хотя возможно лучше, добавить .then для вызова нужной функции после получения ответа. Это может выглядеть как то так
useEffect(() => {
getStore()
.then(res => {
const list = Array.from(new Set(res.result));
dispatch({ type: 'SET_ID', ids: list });
return list;
})
.then(res => {
getProduct(res.slice(firstProductIndex, lastIdIndex))
.then(res => dispatch({ type: 'SET_LIST', products: res.result }));
})
}, []);
Ну и в целом, вызов getProduct(currentIds) без хуков будет приводить к тому, что каждая перерисовка компонента будет вызывать эту функцию, которая тянет перерисовку компонента. Можно получить ошибку To Many ReRender