如何在React中使用getDerivedStateFromProps和setTimeout?

4

我想创建一个类似于模态框的组件,接收一个用于控制打开/关闭的布尔值作为属性,然后将该值存储在组件状态中。当关闭模态框时,我想更新关闭布尔属性,但在更新组件状态之前等待几秒钟,以便可以添加过渡类并对退出进行动画处理。

使用componentWillReceiveProps,我可以通过在超时中包装this.setState并在此期间添加类来实现此目的。使用新的React 16.3 API,我看到推荐使用getDerivedStateFromProps代替。

由于getDerivedStateFromProps "应返回一个对象以更新状态,或返回null表示新属性不需要任何状态更新" (React文档),因此我希望该方法看起来像这样:

static getDerivedStateFromProps(nextProps, prevState) {
    if (nextProps.menuIsOpen === false && prevState.menuIsOpen === true) {
        return setTimeout(() => { menuIsOpen: false}, 1000);
    }
    return null;
}

但那行不通。我已经阅读setTimeout 不返回值的说明,但我想知道是否有比返回一个 Promise 更加优雅的解决方案。


尝试在componentDidUpdate中执行之前的操作,而不是在componentWillReceiveProps中执行。 - Evan Trimboli
1个回答

10

你可以使用componentDidUpdate

componentDidUpdate(prevProps){
    // update your class names...
    if (!this.props.menuIsOpen && this.state.menuIsOpen) {
        setTimeout(() => this.setState({ menuIsOpen: false}), 1000);
    }
}

4
这是正确的。您还需要考虑如果模态框被快速打开和关闭再次打开时应该发生什么,因为如果您不在状态中跟踪isAnimating等内容并且在必要时小心地重置它/取消超时,那么可能会出现竞争条件。一旦您使其正常工作,我建议提取过渡逻辑到一个单独的<DelayProp>组件中,使用render prop API,以便您可以重用它。 - Dan Abramov
我想补充一点,setState 可能会在未挂载的组件上被调用,因为 setTimeout 是异步的,这可能会导致错误。 - Tomasz Mularczyk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接