如何与React Hooks useEffect和setState一起使用setTimeout()?

问题描述 投票:0回答:1

我想等待10秒钟,以便我的API调用从后端获取类别列表数组并以挂接状态存储。如果10秒之内未获取任何内容,我想将错误挂钩状态设置为true。

但是问题是,即使在最初获取数组之后,错误状态也被设置为true,并且处于状态的categoryList数组在10秒后消失了。

import React, { useState, useEffect } from "react";

import { doGetAllCategories } from "../helper/adminapicall.js";

const ViewCategories = () => {
  let [values, setValues] = useState({
    categoriesList: "",
    error: false,
  });

  let { categoriesList, error } = values;

  const preloadCategories = () => {
    doGetAllCategories()
      .then((data) => {
        if (data.error) {
          return console.log("from preload call data - ", data.error);
        }
        setValues({ ...values, categoriesList: data.categories });
      })
      .catch((err) => {
        console.log("from preload - ", err);
      });
  };

  useEffect(() => {
    preloadCategories();

    let timerFunc = setTimeout(() => {
      if (!categoriesList && !error) {
        setValues({
          ...values,
          error: "Error fetching category list... try after some time !",
        });
      }
    }, 10000);

    return () => {
      clearTimeout(timerFunc);
    };
  }, []);



//...further code
javascript reactjs react-hooks settimeout use-effect
1个回答
0
投票

问题是useEffect回调是categoriesList的闭包,因此您将始终在回调中看到初始类别列表,并且看不到任何更改。现在,可以将categoriesList作为依赖项添加到useEffect钩子,这样,在每次categoriesList更改时都将重新创建该钩子,因此您可以看到更改后的版本:

useEffect(/*...*/, [categoriesList]);

现在好事是,通过更新钩子,超时也被取消了,因此,如果设置了类别列表,我们就不必创建新的超时:

  useEffect(() => {
    if(!categoriesList && !error) {
      let timerFunc = setTimeout(() => {
        setValues({
          ...values,
          error: "Error fetching category list... try after some time !",
        });
      }, 10000);

      return () => clearTimeout(timerFunc);
  }
}, [!categoriesList, !error]); // some minor optimization, changes to the list don't bother this hook
© www.soinside.com 2019 - 2024. All rights reserved.