在componentWillReceiveProps中反应设置状态 - 对于此组件和父组件 - 反模式?

时间:2017-07-12 16:03:50

标签: reactjs properties components state

以下代码在我的应用中运行良好。这似乎是一种反模式:

componentWillReceiveProps(nextProps) {
    if (nextProps.conversation.length > this.props.conversation.length){
        if (this.state.hideDiv) {
            this.setState({
                hideDiv: false,
            });
        }
        this.props.incrementNotificationCount();
    }
}

解释

componentWillReceiveProps检查nextProps会话数组是否大于this.props覆盖数组。含义:我收到了一条新的对话信息。

如果我 收到新邮件,我只想在隐藏时显示div ,在this组件中我有本地状态{ {1}}。

如果隐藏:

hideDiv

显示:

if (this.state.hideDiv) 

此外,如果我 收到新邮件,我想增加this.setState({ hideDiv: false, }). 中的通知计数:

parent component

此方法会在this.props.incrementNotificationCount() 中更改通知state

问题

我知道在parent component中设置本地 state不会导致componentWillReceiveProps。但是如果我在rerender中设置state的{​​{1}}会怎样?

这段代码是“反模式”吗?

1 个答案:

答案 0 :(得分:1)

每当父组件重新呈现时,在调用子呈现函数之前调用child中的componentWillReceiveProps。在此函数中,如果为setState调用childComponent,则在componentWillUpdate函数中更新下一个状态,然后由子项中的渲染接收。

同样,当您调用更新父状态的componentWillReceiveProps中的父函数时,父项为rerendered,因此子项将再次重新呈现。

查看演示相同行为的示例代码段

class Parent extends React.Component {
    state = {
      childState: 1,
      mystate: 2,
    }
    changeState = () => {
        console.log('change state in parent called');
        this.setState((prevState) => ({
            mystate: prevState.mystate + 1
        }))
    }
    componentWillUpdate(nextProps, nextState) {
        console.log('cwu parent', nextState);
    }
    changeChildState = () => {
       console.log('change child state called');
       this.setState((prevState) => ({
           childState: prevState.childState + 1
           })
       )
    }
    render() {
        console.log('Parent rerender called');
        return (
           <div>
             <div> Parent {this.state.mystate}</div>
             <button onClick={() => this.changeChildState()}>Click</button>
             <MyComponent val={this.state.childState} changeState={this.changeState}/> 
           </div>
        )
    }
    
   
}

class MyComponent extends React.Component {
        state = {
            someChildState: 1
        }
        componentWillReceiveProps(nextProps) {
            if(nextProps.val !== this.props.val) {
               console.log('child cwrp called');
              this.setState((prevState) => ({someChildState: prevState.someChildState + 1}));
               this.props.changeState();
            }
        }
        componentWillUpdate(nextProps, nextState) {
           console.log(nextState)
        }
        render() {
           console.log('child render called')
           return <div > {this.props.val} {this.state.someChildState} </div>
        }
    }
    
ReactDOM.render(<Parent/>, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>