ES6 - 警告:setState(...):在现有状态转换期间无法更新

时间:2017-01-02 12:30:59

标签: javascript reactjs ecmascript-6

我正在重写一些旧的ReactJS代码,并且无法修复此错误(错误在控制台中重复约1700次,DOM根本不会渲染):

  

警告:setState(...):在现有状态期间无法更新   过渡(例如在render或其他组件内   构造函数)。渲染方法应该是道具的纯函数   州;构造函数的副作用是反模式,但可以移动   到componentWillMount

我是一个组件,它将状态传递给应该呈现某些控件的组件。根据单击的控件,状态应该更改,并且应该呈现新控件。

所以这是我的Container组件:

class TeaTimer extends Component {
    constructor(props) {
        super(props);
        this.state = {
            count: 120,
            countdownStatus: 'started'
        }
    }

    componentDidUpdate(prevProps, prevState) {
        if (this.state.countdownStatus !== prevState.countdownStatus) {
            switch (this.state.countdownStatus) {
                case 'started':
                    this.startTimer();
                    break;
                case 'stopped':
                    this.setState({count:0});
            }
        }
    }

    componentWillUnmount() {
        clearInterval(this.timer);
        delete this.timer;
    }

    startTimer() {
        this.timer = setInterval(() => {
            let newCount = this.state.count -1;
            this.setState({
                count: newCount >= 0 ? newCount : 0
            });
            if(newCount === 0) {
                this.setState({countdownStatus: 'stopped'});
            }
        }, 1000)
    }

    handleStatusChange(newStatus) {
        this.setState({ countdownStatus: newStatus });
    }

    render() {
        let {count, countdownStatus} = this.state;
        let renderStartStop = () => {
            if (countdownStatus !== 'stopped') {
                return <StartStop countdownStatus={countdownStatus} onStatusChange={this.handleStatusChange()}/>
            } else {
                return <div>This will be the slider form</div>
            }
        };
        return(
            <div className={styles.container}>
                <p>This is the TeaTimer component</p>
                <Clock totalSeconds={count}/>
                {renderStartStop()}
            </div>
        )
    }
}

这是我的控制组件:

class StartStop extends Component {
    constructor(props) {
        super(props);
    }

    onStatusChange(newStatus) {
        return() => {
            this.props.onStatusChange(newStatus);
        }
    }

    render() {
        let {countdownStatus} = this.props;

        let renderStartStopButton = () => {
            if(countdownStatus === 'started') {
                return <button onClick={()=> this.onStatusChange('stopped')}>Reset</button>;
            } else {
                return <button onClick={()=> this.onStatusChange('started')}>Start</button>
            }
        };

        return(
            <div className={styles.tt.Controls}>
                {renderStartStopButton()}
            </div>
        )
    }
}

StartStop.propTypes = {
    countdownStatus: React.PropTypes.string.isRequired,
    onStatusChange: React.PropTypes.func.isRequired
};

我很抱歉文字的墙,但我真的可以;弄清楚错误的来源 - 因此不知道我可以省略哪部分代码。

我已尝试实施seemingly related question中找到的解决方案,但无法使其正常运行。

3 个答案:

答案 0 :(得分:7)

我认为你在这一行中有一个错字:

return <StartStop countdownStatus={countdownStatus} onStatusChange={this.handleStatusChange()}/> 

应该是:

return <StartStop countdownStatus={countdownStatus} onStatusChange={() => this.handleStatusChange}/>

您似乎在调用方法handleStatusChange,而不是将其作为回调传递。

答案 1 :(得分:0)

你的metods互相调用,所以你必须定义两个你的metods实例。

class StartStop extends Component {
    constructor(props) {
        super(props);
        this.onStatusChangeReset=this.onStatusChange.bind(this);
        this.onStatusChangeStart=this.onStatusChange.bind(this);

    }

    onStatusChange(newStatus) {
        return() => {
            this.props.onStatusChange(newStatus);
        }
    }

    render() {
        let {countdownStatus} = this.props;

        let renderStartStopButton = () => {
            if(countdownStatus === 'started') {
                return <button onClick={this.onStatusChangeReset('stopped')}>Reset</button>;
            } else {
                return <button onClick={this.onStatusChangeStart('started')}>Start</button>
            }
        };

        return(
            <div className={styles.tt.Controls}>
                {renderStartStopButton()}
            </div>
        )
    }
}

StartStop.propTypes = {
    countdownStatus: React.PropTypes.string.isRequired,
    onStatusChange: React.PropTypes.func.isRequired
};

答案 2 :(得分:-1)

return <StartStop countdownStatus={countdownStatus} onStatusChange={this.handleStatusChange()}/>的这一行给出警告,按下一个试图通过setState关键字改变状态的按钮时调用handleStatusChanged函数。每当状态改变时,再次调用渲染函数,但在你的情况下渲染函数正在返回,而setState关键字再次调用渲染函数。