【问题标题】:How to use setTimeout() along with React Hooks useEffect and setState?如何将 setTimeout() 与 React Hooks useEffect 和 setState 一起使用?
【发布时间】:2020-08-02 19:44:49
【问题描述】:

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

但问题是即使在最初获取数组后,错误状态设置为 true 并且处于状态的 categoriesList 数组在 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】:

    问题在于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
    

    我建议你阅读this blog post on useEffect by Dan Abramov

    【讨论】:

    • 天才 ? 一直在寻找,这就是我所需要的。谢谢朋友,你救了我的一天!
    【解决方案2】:

    您的代码的问题是您希望在 useEffect 挂钩中更改组件的状态。相反,您在 useEffect 中创建两个变量,用于跟踪是否已超过 10 秒的限制或是否获取了数据。与状态变量相反,您可以预期这些变量会发生变化,因为它们位于同一个 useEffect 中。

    export default function App() {
      const [data, setData] = React.useState(null);
      const [error, setError] = React.useState(null);
      React.useEffect(() => {
        let didCancel = false;
        let finished = false;
        async function fetchData() {
          const data = await subscribeAPI();
          if (!didCancel) {
            finished = true;
            setData(data);
          }
        }
        const id = setTimeout(() => {
          didCancel = true;
          if (!finished) {
            setError("Errorrrr");
          }
        }, 10000);
    
        fetchData();
    
        return () => {
          clearTimeout(id);
        };
      }, []);
    

    【讨论】:

      猜你喜欢
      • 2022-11-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-23
      • 2021-07-09
      • 2021-12-09
      • 1970-01-01
      相关资源
      最近更新 更多