使用this.state在渲染中设置状态

时间:2018-04-18 14:44:15

标签: javascript reactjs setstate react-props

我最近看到过这种类型的反应模式,其中使用this.state在渲染中设置状态:

class ShowMe extends React.Component {

    constructor(props) {
        super(props);

        this.state = {
            showButton: false,
        };
    }

    render() {
        if (this.props.show) {
            this.state.showButton = true; //setting state in render!!
        }

        return (
            <div>
                <div> Show or hide button </div>
                {this.state.showButton && <Button content='Btn'/>}
            </div>
        )
    }
}

这似乎是一种反模式。这会导致错误吗?它似乎工作正常。

我只想使用组件生命周期来设置状态:

class ShowMe extends React.Component {

    constructor(props) {
        super(props);

        this.state = {
            showButton: false,
        };
    }

    componentWillReceiveProps(nextProps) {
        if(nextProps.show) {
            this.setState({
                showButton: true,         
            })
        }
     }

    render() {
        return (
            <div>
                <div> Show or hide button </div>
                {this.state.showButton && <Button content='Btn'/>}
            </div>
        )
    }
}

推荐的方式是什么?

3 个答案:

答案 0 :(得分:4)

render应该始终,没有任何副作用,所以这肯定是一种不好的做法。

来自React docs的

  

render()函数应该是纯的,这意味着它不会修改组件状态,每次调用时都返回相同的结果,并且它不直接与浏览器交互。如果需要与浏览器进行交互,请在componentDidMount()或其他生命周期方法中执行您的工作。保持render()纯粹使组件更容易思考。

另请查看herehere

答案 1 :(得分:3)

这是一种反模式。如果showButton状态并不总是等于show props(在示例中就是这种情况),我会使用它:

class ShowMe extends React.Component {

    constructor(props) {
        super(props);

        this.state = {
            showButton: this.props.show,
        };
    }

    componentDidUpdate(prevProps, prevState) {
        prevProps.show !== this.props.show && this.setState({showButton: this.props.show})
    }

    render() {

        return (
            <div>
                <div> Show or hide button </div>
                {this.state.showButton && <Button content='Btn'/>}
            </div>
        )
    }
} 

编辑:从React 16.3开始,在这种情况下应该使用 getDerivedStateFromProps

请注意, componentWillReceiveProps将被弃用。

从文档: getDerivedStateFromProps在实例化组件之后以及接收新道具时调用。它应该返回一个更新状态的对象,或者返回null以指示新的props不需要任何状态更新。

https://reactjs.org/docs/react-component.html#static-getderivedstatefromprops

答案 2 :(得分:1)

渲染方法中的设置状态不正确。您可以在生命周期方法中设置状态。但是其他方面是你的组件可以多次接收相同的道具,因此你的组件将被设置多次状态并进行渲染。要解决此问题,您需要将新的与当前道具进行比较,例如比较json对象:

componentWillReceiveProps(nextProps) {
    if(JSON.stringify(this.props) !== JSON.stringify(nextProps) && nextProps.show) {
        this.setState({
            showButton: true,         
        })
    }
 }

或使用PureComponent。并且,您可以保证您的组件不会不断重新呈现。

如果state.showButton当前设置为true,则不会重新呈现组件会更好。

componentWillReceiveProps(nextProps) {
    if(JSON.stringify(this.props) !== JSON.stringify(nextProps) && nextProps.show) {
       if(!this.state.showButton) {
         this.setState({
            showButton: true,         
        })
       }

    }
 }