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

React setting state in componentWillReceiveProps - for this component and parent component - anti-pattern?

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

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 组件我的本地状态为 hideDiv

如果隐藏:

if (this.state.hideDiv) 

显示它:

this.setState({ 
    hideDiv: false,
}). 

此外,如果我 收到一条新消息,我想增加 parent component 中的通知计数:

this.props.incrementNotificationCount()

此方法会导致通知 stateparent component 中发生更改。

问题

我知道在 componentWillReceiveProps 中设置 local state 不会导致 rerender。但是如果我在 componentWillReceiveProps 中设置 parent componentstate 会发生什么?

这个代码是 "anti-pattern" 吗?

每当父组件重新渲染时, componentWillReceiveProps in child 在调用子渲染函数之前被调用。在此函数中,如果您为 childComponent 调用 setState,下一个状态将在 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>