Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/405.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 带有自定义react钩子的过时状态_Javascript_Reactjs_React Hooks - Fatal编程技术网

Javascript 带有自定义react钩子的过时状态

Javascript 带有自定义react钩子的过时状态,javascript,reactjs,react-hooks,Javascript,Reactjs,React Hooks,const rootElement=document.getElementById(“根”); ReactDOM.render( , 根元素 ) 函数平方(n,超时=1000){ 返回新承诺((解决、拒绝)=>{ setTimeout(()=>resolve(n*n),timeout); }); } 函数App(){ const[number,setNumber]=React.useState(0); 常量[加载、结果、错误、重新加载]=UseAncy( ()=>正方形(数字,1000), [数

const rootElement=document.getElementById(“根”);
ReactDOM.render(
,
根元素
)
函数平方(n,超时=1000){
返回新承诺((解决、拒绝)=>{
setTimeout(()=>resolve(n*n),timeout);
});
}
函数App(){
const[number,setNumber]=React.useState(0);
常量[加载、结果、错误、重新加载]=UseAncy(
()=>正方形(数字,1000),
[数字]
);
控制台日志(编号、结果);
返回(
减量{“}
setNumber(number=>setNumber(number-1))}
>
-
编号:{Number}
其平方:{result}{loading&&}
增量
setNumber(number=>setNumber(number+1))}
>
+
);
}
函数useAncy(func,dependencyArray=[]){
常量[状态,设置状态]=React.useState({
加载:false,
结果:空,
错误:null,
是的
});
常量重新加载=()=>{
函数调用(){
设置状态(状态=>({
……国家,
加载:对,
错误:null,
结果:空
}));
func()
。然后(res=>{
如果(!state.mounted)返回;
设置状态(状态=>({
……国家,
结果:res,,
加载:错误
}));
})
.catch(错误=>{
设置状态(状态=>({
……国家,
加载:false,
结果:空,
错误
}));
})        
}
call();
};
React.useffect(()=>{
重新加载();
return()=>
设定状态({
……国家,
加载:false,
结果:空,
错误:null
});
},依赖数组);
React.useffect(()=>{
setState(state=>({…state,mounted:true}));
return()=>setState(state=>({…state,mounted:false}));
}, []);
返回[state.loading,state.result,state.error,reload,setState];
}
.App{
字体系列:无衬线;
文本对齐:居中;
显示器:flex;
调整内容:灵活启动;
调整项目:灵活启动;
弯曲方向:立柱;
}
钮扣{
宽度:100px;
高度:40px;
边界半径:4px;
}

您在控制台中看到null,因为当数字更改时,您正在重置自定义挂钩内的状态,使其在重载函数以及useEffect的清除函数中具有
result=null

const reload = () => {
    async function call() {
      try {
        setState(state => ({
          ...state,
          loading: true,
          error: null,
          result: null
        }));
        const res = await func();
        if (!state.mounted) return;
        setState(state => ({
          ...state,
          result: res,
          loading: false
        }));
      } catch (error) {
        if (!state.mounted) return;
        setState(state => ({
          ...state,
          loading: false,
          result: null,
          error
        }));
      }
    }
    call();
  };
如果您不想将值重置为null,并且只在计算完成后更新它,那么可以避免重置值,但我建议您继续执行您所做的操作,因为它可以更好地处理场景,并且由于您已将状态加载设置为true,因此您可以显示加载程序,直到获取结果

但是,您可以删除useEffect的清除函数中的setState,这是不需要的

const reload = () => {
    async function call() {
      try {
        setState(state => ({
          ...state,
          loading: true,
        }));
        const res = await func();
        if (!state.mounted) return;
        setState(state => ({
          ...state,
          result: res,
          loading: false
        }));
      } catch (error) {
        if (!state.mounted) return;
        setState(state => ({
          ...state,
          loading: false,
          result: null,
          error
        }));
      }
    }
    call();
  };

  React.useEffect(() => {
    reload();
  }, dependencyArray);

当您多次单击递增或递减按钮时,您有多个未兑现的承诺。然后,
result
只是随着每个承诺的解决而更新

如果您主要关心的是确保用户没有看到不正确的结果,则可以让传递的函数返回一个包含原始参数和答案的数组,然后检查以确保
number
的当前值与之匹配:

function square(n, timeout = 1000) {
  return new Promise((resolve, reject) => {
    setTimeout(() => resolve([n, n * n]), timeout);
  });
}

export default function App() {
  const [number, setNumber] = useState(0);
  const [loading, argAndResult, error, reload] = useAsync(
    () => square(number, 1000),
    [number]
  );
  if (argAndResult && argAndResult[0] === number) 
      { result = argAndResult[1]; }
  else { result = null; }

虽然不理想,但在某些使用情况下仍能正常工作。

感谢您提供有用的链接@T.J.Crowder。我已经做了适当的修改。谢谢你的回答@shubham。但是null完全是故意的,不是bug。当我的应用程序打印34时,这是一个错误,因为4是2的平方,这是以前的状态。我已经创建了工作代码段。请跑过去看看。错误只在控制台中可见。我看不到它在任何时候打印34当数字设置为2时,你增加它,它将打印34。请先把数字增加到2。然后再增加一次。您将看到3 4。这是因为UseAncy中的useEffect只有在更改了数字后才会触发,因此会使用大于useEffect的递增数字进行重新渲染,并将状态设置为null,然后在数据可用时将其设置为正确的值。我希望这能向您解释情况,如果您有疑问,请让我知道问题不是因为多个未兑现的承诺@jdaz。我已经更新了演示,在加载时,两个按钮都将被禁用。因此,没有多个未兑现的承诺。但你可以看到这个问题仍然存在。