Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/26.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 函数A依赖于上一个函数来更新状态,但函数A仍会在更新之前尝试渲染_Javascript_Reactjs_Use State - Fatal编程技术网

Javascript 函数A依赖于上一个函数来更新状态,但函数A仍会在更新之前尝试渲染

Javascript 函数A依赖于上一个函数来更新状态,但函数A仍会在更新之前尝试渲染,javascript,reactjs,use-state,Javascript,Reactjs,Use State,下面我链接了一个例子,说明了我的问题 我的问题 我有这两个功能 const updatedoc=checkForHeadings(stoneCtx,documentCtx);//返回对象 documentCtx.setUserDocument(updateDoc);//使用对象更新状态 及 convertUserDocument(stoneCtx,documentCtx.userDocument); //使用状态以供进一步使用 我遇到的问题是,convertUserDocument以空状态运

下面我链接了一个例子,说明了我的问题

我的问题 我有这两个功能

const updatedoc=checkForHeadings(stoneCtx,documentCtx);//返回对象
documentCtx.setUserDocument(updateDoc);//使用对象更新状态

convertUserDocument(stoneCtx,documentCtx.userDocument);
//使用状态以供进一步使用
我遇到的问题是,
convertUserDocument
以空状态运行并抛出错误,然后以更新状态再次运行。因为它已经抛出了一个错误,我无法继续处理它

我试过几种不同的方法

我试过的 一开始我的代码是这样的

检查标题(stoneCtx、documentCtx);
//更新了函数中每个新键:值的状态
convertUserDocument(stoneCtx,documentCtx.userDocument);
//然后运行这个函数;错误
然后我尝试了上面的版本,首先将所有内容放入一个对象中,只更新一次状态

convertUserDocument
作为
checkForHeadings
内部的回调,但多次运行该回调时,找到了匹配的键

我当前的尝试是将这两个函数分别放在
useffect
s中,一个用于初始渲染,另一个用于下一个渲染

const isFirstRender=useRef(true);
设init=0;
useffect(()=>{
init++;
log('初始渲染编号'+init);
console.log(documentCtx);
const updatedoc=检查标题(stoneCtx.stoneContext,documentCtx);
documentCtx.setUserDocument(updateDoc);
console.log(updatedoc);
console.log(documentCtx);
isFirstRender.current=false;//第一次渲染/装载后切换标志
log('Initial End Render Number'+init);
}, []);
让update=0;
useffect(()=>{
更新++;
console.log('Update Render Number'+Update);
如果(!isFirstRender.current){
log('第一次渲染已发生');
convertUserDocument(stoneCtx.stoneContext,documentCtx.userDocument);
}
console.log('Update End Render Number'+Update);
},[documentCtx]);
有趣的是,我看到了Codesandbox和我的本地开发之间的区别。
在Codesandbox上,初始渲染被调用了两次,但每次计数器没有上升,它都保持在1。另一方面,在我的本地开发服务器上,只调用了一次初始渲染。
在两个版本中,第二个
useffect
被调用了两次,但这里的计数器也没有上升到2,而是保持在1。 代码沙盒:

本地开发服务器:

举个简单的例子:

let计数器=0;
useffect(()=>{
计数器++;
//这应该只运行一次,但在沙箱中会运行两次。
//但是计数器不会上升到2,而是保持在1
},[])
第二个
useffect
也会发生同样的情况,但在第二个
useffect时,我得到了不同的结果,但计数器保持在1。
我被告知这是由于一个陈旧的Cloruse,但没有解释为什么重要的部分不能正常工作

我从这里得到了灵感,跳过了最初的渲染:

代码 下面是显示问题的沙箱:
我还在Stackblitz上创建了它:

此函数中发生错误:

功能订单文档(结构、文档、订单){
结构.forEach((el)=>{
控制台日志(el.id);
控制台日志(doc);
//订单推送(doc[el.id].headingTML);
//if(el.儿童?长度){
//orderDocument(el.children、doc、ordered);
// }
});
订购退货;
}
注释掉的代码抛出错误。我是console.loggin
el.id
doc
,在控制台中,您可以看到
doc
是空的,因此无法找到
doc[el.id]

有人给我举了一个简单的例子来说明我的问题,总结得很好

useffect(()=>{
documentCtx.setUserDocument(“任何东西”);
console.log(documentCtx.userDocument);
});
控制台:

{}
ANYTHING
您可以在此处查看:


我已经找到了解决我问题的办法

const isFirstRender=useRef(true);
useffect(()=>{
const updatedoc=检查标题(stoneCtx.stoneContext,documentCtx);
documentCtx.setUserDocument(updateDoc);
}, []);
useffect(()=>{
如果(!isFirstRender.current){
convertUserDocument(stoneCtx.stoneContext,documentCtx.userDocument);
}否则{
isFirstRender.current=false;
}
},[documentCtx]);
移动
isFirstRender.current=false到else语句实际上为我提供了所需的正确结果。

这是实现它的最佳方式,还是有更好的方式?

很抱歉,我只读了第一段,但是如何将第一个渲染条件更改为非初始状态?@k-wasilewski很抱歉,但是什么是
状态非初始条件
?来检查状态是否为空(然后不执行任何操作)或是否已更新(然后执行此
convertUserDocument
)。当对象开始时为空时,这可能会起作用,但稍后当它已经有内容时,它可能仍会遇到错误,因为它尚未更新。组件呈现生命周期中正在进行的状态更新是什么?如果您只需要不在初始呈现上运行效果回调,则请使用ref“hack”是解决方案。我倾向于同意@k-wasilewski的观点,尽管它从不同的初始状态开始,并做一个条件测试来运行
convertUserDocument
。我认为更大的问题/问题可能是,为什么要在更新的内容和
convertUserDocument
函数之间进行如此紧密的耦合。也许更重要的问题是全面的组件代码示例将对我们有所帮助