Обновление состояния с помощью fetch с последующим использованием состояния в useEffect не работает - PullRequest
0 голосов
/ 13 февраля 2020

У меня есть компонент в React, где в useEffect я делаю два вызова API и устанавливаю два состояния. После того, как я все еще в useEffect, я пытаюсь установить другое состояние с одним из состояний, обновленных API. Если я сделаю это, оставив параметр в квадратных скобках useEffect пустым, состояние не будет установлено. Если я передаю константы состояния в скобках, они переходят в бесконечное число l oop.

async function fetchData() {
    const agentRes = await fetch("http://localhost:3004/agentsdata");
        agentRes
            .json()
            .then(res => setAgents(res))
            .catch(err => console.log(err));

    const queueRes = await fetch("http://localhost:3004/queuedata");
        queueRes
            .json()
            .then(res => setBaseQueues(res))
            .catch(err => console.log(err));
    }

useEffect(() => {

    fetchData();

    let pge;

    if (props.location.data !== undefined) {
        pge = props.location.data.page;
    }
    else {pge = 1;}

    setUser(props.match.params.user);
    setPage(pge);


    let lowerB = (0 +((pge - 1) * 10));
    let upperB = 10 + ((pge - 1) * 10);

    setQueues(baseQueues.slice(lowerB, upperB)); // here the state is not getting set.
}, [queues])

Как мне сделать так, чтобы я мог установить это состояние так же, как мне нужно сделать это в useEffect.

Ответы [ 3 ]

2 голосов
/ 13 февраля 2020

useEffect(() => {
  const doAsyncStuff = async () => {
     await fetchData(); // wait for this data to load
     const { data } = props.location;
     let pge = data !== undefined ? data.page : 1;
     setUser(props.match.params.user);
     setPage(pge);
     
     let lowerB = (0 +((pge - 1) * 10));
     let upperB = 10 + ((pge - 1) * 10);
     
     setQueues(state => state.slice(lowerB, upperB)); // change here
  }
  doAsyncStuff();
}, [queues])

Сначала я думаю, что вам нужно дождаться загрузки данных, поэтому вам нужно дождаться await fetchData();

, а затем при установке setQueues ты должен сделать setQueues(state => state.slice(lowerB, upperB));

0 голосов
/ 13 февраля 2020

Я попытался исправить код и дал подробное объяснение в комментариях о том, как правильно использовать ловушку useEffect. Я настоятельно рекомендую вам прочитать эту запись в блоге Дэна Абрамова, она прояснит большинство ваших неправильных представлений об использовании useEffect ловушки

//since you data fetching code does not depend on anything inside your component you can hoist it outside the component.

async function getAgentData(){
  try{
     const response = await fetch('http://localhost:3004/agentsdata');
     return await response.json();
  } catch(error){
    console.log(error)
  }
}

async function getQueueData{
  try{
     const response = await fetch('http://localhost:3004/queuedata');
     return await response.json();
  } catch(error){
    console.log(error)
  }
}


function YourComponent(props){

   // destructure your props
   const { location: { data }, match } = props;
   const { params: { user } } = props.match;

   // Split your hooks by concern keep the related code together
   useEffect(() => {

      setUser(user);

   // add ALL you dependencies for this effect
   }, [user])

   // Second Effect
   useEffect(() => {

     const pge = (data == undefined)? 1 : data.page;
     const lowerB = (0 +((pge - 1) * 10));
     const upperB = 10 + ((pge - 1) * 10);

     setPage(pge);

     async function fetchData(){
       const agentRes = await getAgentData();
       setAgents(agentRes);

       const queueRes = await getQueueData();

       // Note: There need to first save it to state; then retrieve then slice then update again. When all you need is this
       setBaseQueues(queueRes.slice(lowerB, upperB));
     }

     //call the function here
     fetchData();

     //Add the ALL the dependencies of this effect i.e all props, functions, state variables inside 
     //YourComponent that you have used in this effect
     //In this case this effect is only run when this.props.location.data is changes, which is the desired behaviour
   }, [ data ])

   return <>Whatever</>
}

0 голосов
/ 13 февраля 2020

Вы можете использовать более простую химию:

useEffect(() => {
  fetchData();
}, [queues])

useEffect(() => {
  let pge;

  if (props.location.data !== undefined) {
      pge = props.location.data.page;
  }
  else {pge = 1;}

  setUser(props.match.params.user);
  setPage(pge);

  let lowerB = (0 +((pge - 1) * 10));
  let upperB = 10 + ((pge - 1) * 10);

  setQueues(baseQueues.slice(lowerB, upperB)); // here baseQueues is updated.
}, [baseQueues])

... , но, вероятно, вам не нужно большинство из этого

  • queues являются производные данные;
  • это подмножество может быть «вычислено» для каждого рендера после смены страницы;
  • после загрузки страницы параметр может выйти за пределы диапазона - перенаправить ?;
...