【问题标题】:React state is overwritten to empty in componentDidUpdate after it was set to a value将 React 状态设置为值后,在 componentDidUpdate 中将其覆盖为空
【发布时间】:2019-10-15 15:55:37
【问题描述】:

我正在编写一个注册组件并根据服务器使用 Redux 的响应在componentDidUpdate 中设置错误,但在提交时,状态稍后会在几秒钟后设置为空,即在错误消息设置为状态之后立即设置,它又被设置为空。

state = {
    firstName: "",
    lastName: "",
    email: "",
    password: ""
    msg: null,   
};  

componentDidUpdate(prevProps) {
    const { error } = this.props;

    if (error !== prevProps.error) {
        // check for register error
        if (error.id === "REGISTER_FAIL") {
            this.setState({ msg: error.msg.message });
        } else {
            this.setState({ msg: "null" });
        }
    }
}

render() {
    console.log(this.state)
}

我希望在this.state.msg 中收到错误消息,但我得到一个空的this.state.msg,而错误存在于错误道具中。

【问题讨论】:

    标签: reactjs react-redux


    【解决方案1】:

    我认为处理这种情况并避免重新渲染/无限循环的最佳方法是在react 生命周期的getDerivedStateFromProps 方法中处理它。

    state = {
        firstName: "",
        lastName: "",
        email: "",
        password: ""
        msg: null,
        prevPropMsg: null // we don't need this state, we can re-use msg state if you are not mutating msg state apart from in getDerivedStateFromProps method
    };  
    
    static getDerivedStateFromProps(nextProps, prevState) {
        if (nextProps.error !== prevState.prevPropMsg) {
            // check for register error
            if (nextProps.error.id === "REGISTER_FAIL") {
                return { 
                   msg: nextProps.error.msg.message,
                   prevPropMsg: nextProps.error.msg.message
                };
            } else {
                return { 
                   msg: null,
                   prevPropMsg: null
                };
            }
        }
    
        return null;
    }
    
    render() {
        console.log(this.state)
    }
    
    

    【讨论】:

      【解决方案2】:

      当您从componentDidUpdate 调用setState 时,您的组件将立即重新渲染。如果您没有在else 条件下调用setState,这将是可以的。我相信正在发生的事情是您正在设置错误,您的组件重新渲染,并且您的 else 条件重置了消息。通过检查以下输出来验证这一点:

      componentDidUpdate(prevProps) { 
        const { error } = this.props;
        if (error !== prevProps.error) {
          // check for register error
          if (error.id === "REGISTER_FAIL") {
            this.setState({ msg: error.msg.message });
            console.log('if');
          } else {
            this.setState({ msg: null });
            console.log('else');
          }
        }
      }
      

      如果两者都在开火。这将确认您的问题。

      来自docs

      您可以立即在 componentDidUpdate() 中调用 setState(),但请注意,它必须像上面示例中那样包含在条件中,否则会导致无限循环。它还会导致额外的重新渲染,虽然对用户不可见,但会影响组件的性能。如果您尝试将某些状态“镜像”到来自上方的道具,请考虑直接使用道具。阅读有关why copying props into state causes bugs 的更多信息。

      【讨论】:

        猜你喜欢
        • 2020-10-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-03
        • 2020-11-02
        • 2017-10-17
        • 1970-01-01
        相关资源
        最近更新 更多