web-dev-qa-db-ja.com

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;
151
user3611459

Renderメソッドで誤ってhandleButtonChangeメソッドを呼び出しているように見えますが、代わりにonClick={() => this.handleButtonChange(false)}を実行することをお勧めします。

OnClickハンドラでラムダを作成したくない場合は、各パラメータに1つずつ、合計2つのメソッドを用意する必要があります。

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>
261

理解を深めるために、一般的な例を挙げています。

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>
    )
  }
4
Ignatius Andrew

recomposeでハンドラーに引数を追加しようとしている場合は、ハンドラーで引数を正しく定義していることを確認してください。それは本質的にカリー化された関数なので、あなたは確実に正しい数の引数を要求したいと思うでしょう。 このページには、ハンドラーで引数を使用する良い例があります。

例(リンクから):

withHandlers({
  handleClick: props => (value1, value2) => event => {
    console.log(event)
    alert(value1 + ' was clicked!')
    props.doSomething(value2)
  },
})

あなたの子供のためにHOCそして親の中に

class MyComponent extends Component {
  static propTypes = {
    handleClick: PropTypes.func, 
  }
  render () {
    const {handleClick} = this.props
    return (
      <div onClick={handleClick(value1, value2)} />
    )
  }
}

これはあなたのハンドラから十分なパラメータ名を供給しないという問題を修正するためにあなたのハンドラから無名関数を書くことを避けます。

3
Nick Brady

反応ドキュメントから イベントハンドラに引数を渡す

<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
2
Rahil Ahmad

これと同じ警告が、render()呼び出しで行われたすべての状態変更に対して発行されます。

ケースを見つけるのが難しい例:状態データに基づいて複数選択GUIコンポーネントをレンダリングするときに、stateに何も表示されない場合、resetOptions()の呼び出しはそのコンポーネントの状態変更と見なされます。

明らかな修正はresetOptions()の代わりにcomponentDidUpdate()render()を行うことです。

2
Jari Turkia

電話をかけていたときに同じエラーが発生しました

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

handleClickが存在しなかったときの私のコンストラクタの中で

(私はそれを消してしまい、誤って "this"というバインディングステートメントをコンストラクタに残していました)。

解決策= "this"バインディングステートメントを削除してください。

1
Sam Henderson

Popover for componentsを開くために私が使用する解決策は reactstrap(React Bootstrap 4 components) です。

    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>
        }
    }
0
dev-siberia

OnClickハンドラでボタンを貸している間の問題は確かにthisバインディングです。解決策は、レンダリング中にアクションハンドラを呼び出すときに矢印関数を使用することです。このように:onClick={ () => this.handleButtonChange(false) }

0
FEUYAN TCHOUO