我有一个Parent react组件,其中有多个通过.map()
函数创建的子组件。我正在传递函数addCallback()
作为子道具,因此我有一个引用,可以通过父项触发所有子项的handleRun()
函数。
我正在尝试将所有子代都在运行时将我的父级组件的状态更新为running = true
,并将所有子代都已完成运行时的状态更新为running = false
并在父级上呈现该状态。但是状态似乎没有按照我指定的特定顺序更新。
这是我的做法:
let promise1 = this.setState({isRunning: true},
() => {
this.state.childRef.map(x => x())
});
Promise.all([promise1])
.then(() => this.setState({isRunning: false}))
这是codesandbox中的全部代码:link
感谢您的帮助,因为我对React(和Javascript)还很陌生。谢谢!
答案 0 :(得分:2)
原因runSomething
不是Promise
。你必须改变。
runSomething() {
return new Promise((resolve, reject) => {
this.setState({ status: "running" });
// simulate running something that takes 8s
setTimeout(() => {
this.setState({ status: "idle" });
resolve(true);
}, 3000);
});
}
答案 1 :(得分:2)
在函数声明中使用异步会自动返回一个Promise,该Promise会围绕您从函数返回的内容进行包装。您的情况是undefined
。这就是为什么您当前的代码目前不会引发任何错误的原因。
您将需要一种机制来等待setTimeout
。像这样更改runSomething
函数将起作用
async runSomething() {
this.setState({ status: "running" });
// simulate running something that takes 8s
return new Promise(resolve => {
setTimeout(() => {
this.setState({ status: "idle" }, resolve);
}, 3000);
});
}
请注意第this.setState({ status: "idle" }, resolve);
行。它确保您的诺言不仅在setTimeout
之后得到解决,而且在孩子的状态更改为“ idle”之后也得到解决。这是您的子组件已变为“空闲”状态的正确指示。
答案 2 :(得分:0)
这是您要实现的沙箱实现。 Sanbox
在这里我已经在父组件中创建了一个状态,该状态将在运行子项时更新。
this.state = {
callbacks: [],
components: [
{
index: 0, // we don't need this field its just for your info you can just create [true,false] array and index will represent component index.
status: false
},
{
index: 1,
status: false
}
]
};
当组件数组中的所有状态均为true时,我们会将parent的空闲状态更新为running。
getAllRunningStatus() {
let { components } = this.state;
let checkAllRunning = components.map(element => element.status);
if (checkAllRunning.indexOf(false) === -1) { // you can also use !includes(false)
return true;
}
return false;
}
内部渲染功能
<h1>Parent {this.getAllRunningStatus() ? "running" : "idle"}</h1>
注意:-我刚刚写了一个粗糙的代码。您可以根据需要对其进行优化。谢谢