我想等待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
答案 0 :(得分: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
答案 1 :(得分:0)
您的代码存在问题,因为您希望在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);
};
}, []);