Как выводить запросы пока не будет получен нормальный ответ с сервера

у меня есть компонент 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 шт):

Автор решения: SwaD

Положите вызов функции в 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

→ Ссылка