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

use*_*459 175 constructor setstate reactjs

我试图从我的渲染视图重构以下代码:

<Button href="#" active={!this.state.singleJourney} onClick={this.handleButtonChange.bind(this,false)} >Retour</Button>
Run Code Online (Sandbox Code Playgroud)

到绑定在构造函数中的版本.原因是渲染视图中的绑定会给我带来性能问题,特别是在低端手机上.

我创建了以下代码,但我不断收到以下错误(很多错误).看起来应用程序进入循环:

Warning: setState(...): Cannot update during an existing state transition (such as within `render` or another component's constructor). Render methods should be a pure function of props and state; constructor side-effects are an anti-pattern, but can be moved to `componentWillMount`.
Run Code Online (Sandbox Code Playgroud)

以下是我使用的代码:

var React = require('react');
var ButtonGroup = require('react-bootstrap/lib/ButtonGroup');
var Button = require('react-bootstrap/lib/Button');
var Form = require('react-bootstrap/lib/Form');
var FormGroup = require('react-bootstrap/lib/FormGroup');
var Well = require('react-bootstrap/lib/Well');

export default class Search extends React.Component {

    constructor() {
        super();

        this.state = {
            singleJourney: false
        };

        this.handleButtonChange = this.handleButtonChange.bind(this);
    }

    handleButtonChange(value) {
        this.setState({
            singleJourney: value
        });
    }

    render() {

        return (
            <Form>

                <Well style={wellStyle}>

                    <FormGroup className="text-center">

                        <ButtonGroup>
                            <Button href="#" active={!this.state.singleJourney} onClick={this.handleButtonChange(false)} >Retour</Button>
                            <Button href="#" active={this.state.singleJourney} onClick={this.handleButtonChange(true)} >Single Journey</Button>
                        </ButtonGroup>
                    </FormGroup>

                </Well>

            </Form>
        );
    }
}

module.exports = Search;
Run Code Online (Sandbox Code Playgroud)

Vla*_*sky 289

看起来你不小心handleButtonChange在你的渲染方法中调用了这个方法,你可能想要这样做onClick={() => this.handleButtonChange(false)}.

如果您不想在onClick处理程序中创建lambda,我认为您需要有两个绑定方法,每个参数一个.

constructor:

this.handleButtonChangeRetour = this.handleButtonChange.bind(this, true);
this.handleButtonChangeSingle = this.handleButtonChange.bind(this, false);
Run Code Online (Sandbox Code Playgroud)

并在render方法中:

<Button href="#" active={!this.state.singleJourney} onClick={this.handleButtonChangeSingle} >Retour</Button>
<Button href="#" active={this.state.singleJourney} onClick={this.handleButtonChangeRetour}>Single Journey</Button>
Run Code Online (Sandbox Code Playgroud)

  • 主要区别在于onClick = {this.handleButtonChange(false)}和onClick = {()=> this.handleButtonChange(false)} - 第一个错误,因为它只是立即调用handleButtonChange方法并赋予其返回值(未定义)到onClick句柄 - 因此没有任何反应.第二个实际上为onClick指定了一个方法 - 一个调用handleButtonChange的方法. (23认同)
  • 也许会发生什么是当我设置活动状态时,它会触发onClick,从而导致循环.有没有办法在不触发onClick的情况下设置活动状态? (2认同)
  • 为什么lambda是解决方案?这背后是哪个概念?我看不到. (2认同)

Gal*_*cha 11

这通常发生在你打电话时

onClick={this.handleButton() }- 注意()而不是:

onClick={this.handleButton} - 注意这里我们没有在初始化函数时调用它


小智 9

问题就在这里:onClick={this.handleButtonChange(false)}

当您传递this.handleButtonChange(false)给 onClick 时,您实际上是在调用该函数并将value = falseonClick 设置为该函数的返回值(未定义)。此外,调用this.handleButtonChange(false)then 会触发 this.setState()重新渲染,从而导致无限渲染循环。

解决方案是在 lambda: 中传递函数onClick={() => this.handleButtonChange(false)}。在这里,您将 onClick 设置为等于单击按钮时将调用 handleButtonChange(false) 的函数。

下面的例子可能会有所帮助:

function handleButtonChange(value){
  console.log("State updated!")
}

console.log(handleButtonChange(false))
//output: State updated!
//output: undefined

console.log(() => handleButtonChange(false))
//output: ()=>{handleButtonChange(false);}
Run Code Online (Sandbox Code Playgroud)


Ign*_*rew 8

我在下面的代码中提供了一个通用示例,以使您更好地理解

render(){
    return(
      <div>

        <h3>Simple Counter</h3>
        <Counter
          value={this.props.counter}
          onIncrement={this.props.increment()} <------ calling the function
          onDecrement={this.props.decrement()} <-----------
          onIncrementAsync={this.props.incrementAsync()} />
      </div>
    )
  }
Run Code Online (Sandbox Code Playgroud)

提供道具时,我直接调用该函数,该循环执行无限循环,并且会给您该错误,删除该函数可以正常工作。

render(){
    return(
      <div>

        <h3>Simple Counter</h3>
        <Counter
          value={this.props.counter}
          onIncrement={this.props.increment} <------ function call removed
          onDecrement={this.props.decrement} <-----------
          onIncrementAsync={this.props.incrementAsync} />
      </div>
    )
  }
Run Code Online (Sandbox Code Playgroud)