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

我正在尝试从渲染视图重构以下代码:

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

到绑定位于构造函数内的版本。原因是渲染视图中的绑定会给我带来性能问题,尤其是在低端手机上。

我创建了以下代码,但是我不断收到以下错误(很多错误)。该应用似乎陷入了循环:

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`.

以下是我使用的代码:

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;
村村神无猴子2020/03/11 10:55:05

我用来为组件打开Popover的解决方案是reactstrap(React Bootstrap 4组件)

    class Settings extends Component {
        constructor(props) {
            super(props);

            this.state = {
              popoversOpen: [] // array open popovers
            }
        }

        // toggle my popovers
        togglePopoverHelp = (selected) => (e) => {
            const index = this.state.popoversOpen.indexOf(selected);
            if (index < 0) {
              this.state.popoversOpen.push(selected);
            } else {
              this.state.popoversOpen.splice(index, 1);
            }
            this.setState({ popoversOpen: [...this.state.popoversOpen] });
        }

        render() {
            <div id="settings">
                <button id="PopoverTimer" onClick={this.togglePopoverHelp(1)} className="btn btn-outline-danger" type="button">?</button>
                <Popover placement="left" isOpen={this.state.popoversOpen.includes(1)} target="PopoverTimer" toggle={this.togglePopoverHelp(1)}>
                  <PopoverHeader>Header popover</PopoverHeader>
                  <PopoverBody>Description popover</PopoverBody>
                </Popover>

                <button id="popoverRefresh" onClick={this.togglePopoverHelp(2)} className="btn btn-outline-danger" type="button">?</button>
                <Popover placement="left" isOpen={this.state.popoversOpen.includes(2)} target="popoverRefresh" toggle={this.togglePopoverHelp(2)}>
                  <PopoverHeader>Header popover 2</PopoverHeader>
                  <PopoverBody>Description popover2</PopoverBody>
                </Popover>
            </div>
        }
    }
不知2020/03/11 10:55:05

我打电话时遇到了同样的错误

this.handleClick = this.handleClick.bind(this);

在我的构造函数中,当handleClick不存在时

(我已经删除了它,并且不小心将“ this”绑定语句留在了我的构造函数中)。

解决方案=删除“ this”绑定语句。

西里泡芙2020/03/11 10:55:05

问题当然是在绑定带有onClick处理程序的按钮时的绑定。解决方案是在渲染时调用动作处理程序时使用箭头功能。像这样: onClick={ () => this.handleButtonChange(false) }

蛋蛋西门2020/03/11 10:55:05

render()呼叫中发生的任何状态更改都将发出相同的警告

一个棘手的例子:在基于状态数据呈现多选GUI组件时,如果state没有要显示的内容,resetOptions()则对该组件的调用被视为状态更改。

明显的解决方法是用resetOptions()in componentDidUpdate()代替render()

ProSam2020/03/11 10:55:05

来自react docs将参数传递给事件处理程序

<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
LEY逆天2020/03/11 10:55:05

通常发生在您打电话时

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

onClick={this.handleButton} -请注意,我们在初始化函数时并未调用该函数

村村达蒙LEY2020/03/11 10:55:05

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

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>
    )
  }

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

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>
    )
  }
理查德Near2020/03/11 10:55:05

看起来您不小心handleButtonChange在render方法中调用了该方法,而您可能想这样做onClick={() => this.handleButtonChange(false)}

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

constructor

this.handleButtonChangeRetour = this.handleButtonChange.bind(this, true);
this.handleButtonChangeSingle = this.handleButtonChange.bind(this, false);

并在render方法中:

<Button href="#" active={!this.state.singleJourney} onClick={this.handleButtonChangeSingle} >Retour</Button>
<Button href="#" active={this.state.singleJourney} onClick={this.handleButtonChangeRetour}>Single Journey</Button>