267 votes

ReactJS : Warning : setState(...) : Impossible de mettre à jour pendant une transition d'état existante

J'essaie de remanier le code suivant de ma vue de rendu :

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

à une version où le bind se trouve dans le constructeur. La raison en est que le bind dans la vue de rendu me donnera des problèmes de performance, en particulier sur les téléphones mobiles bas de gamme.

J'ai créé le code suivant, mais je reçois constamment les erreurs suivantes (beaucoup d'erreurs). Il semble que l'application soit dans une boucle :

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

Voici le code que j'utilise :

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;

0 votes

J'ai le même problème, mais lié à onClick() : stackoverflow.com/questions/57079814/

0 votes

Même problème mais sans onClick() : stackoverflow.com/questions/57079814/

383voto

Vladimir Rovensky Points 2730

Il semble que vous appeliez accidentellement la fonction handleButtonChange dans votre méthode de rendu, vous voudrez probablement utiliser la méthode onClick={() => this.handleButtonChange(false)} au lieu de cela.

Si vous ne voulez pas créer une lambda dans le gestionnaire onClick, je pense que vous devrez avoir deux méthodes liées, une pour chaque paramètre.

Dans le cadre de la constructor :

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

Et dans le render méthode :

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

0 votes

J'ai essayé cette solution et elle fonctionne. Mais je ne vois nulle part cette solution en ligne comme solution préférée. Ce que je veux accomplir, c'est que mon bind soit en dehors de la vue de rendu. Dans cette solution, this.handleButtonChange = this.handleButtonChange.bind(this) ; dans le constructeur n'est plus nécessaire, est-ce que cela signifie que mon binding est à nouveau dans ma vue de rendu ?

2 votes

Peut-être que ce qui se passe, c'est que lorsque je définis l'état actif, cela déclenche onClick, ce qui entraîne une boucle. Existe-t-il un moyen de définir l'état actif sans déclencher onClick ?

2 votes

Pourquoi une lambda est-elle la solution ? Quel est le concept sous-jacent ? Je ne le vois pas.

4voto

Nick Brady Points 1844

I recompose , T

E

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

f

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

t

2voto

Rahil Ahmad Points 755

F P

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

1voto

Sam Henderson Points 151

I

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

i h

(

S

0voto

dev-siberia Points 301

T r .

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X