web-dev-qa-db-fra.com

Effacement de l'état es6 React

J'essaie d'effacer un composant state mais je ne trouve pas de référence pour la syntaxe es6. J'utilisais:

this.replaceState(this.getInitialState());

cependant, cela ne fonctionne pas avec la syntaxe de classe es6.

Comment pourrais-je atteindre le même résultat?

37
Guy

Autant que je sache, les composants de React ne conservent pas de copie de l'état initial, vous devez donc le faire vous-même.

const initialState = {
    /* etc */
};

class MyComponent extends Component {
    constructor(props) {
        super(props)
        this.state = initialState;
    }
    reset() {
        this.setState(initialState);
    }
    /* etc */
}

Attention, la ligne this.state = initialState; vous oblige à ne jamais muter votre état, sinon vous pollueriez initialState et rendriez une réinitialisation impossible. Si vous ne pouvez pas éviter les mutations, vous devrez créer une copie de initialState dans le constructeur. (Ou faites de initialState une fonction, conformément à getInitialState().)

Enfin, je vous recommande d’utiliser setState() et non replaceState().

66
David L. Walsh

Problème

Le réponse acceptée:

const initialState = {
    /* etc */
};

class MyComponent extends Component {
    constructor(props) {
        super(props)
        this.state = initialState;
    }
    reset() {
        this.setState(initialState);
    }
    /* etc */
}

est malheureusement pas correct.

initialState est passé comme référence à this.state. Ainsi, chaque fois que vous changez state, vous changez également initialState (const n'a pas d'importance ici. Le résultat est que vous ne pouvez jamais revenir à initialState.

Solution

Vous devez copier en profondeurinitialState à state, alors cela fonctionnera. Ecrivez vous-même une fonction de copie en profondeur ou utilisez un module existant tel que this .

33
RaptoX

C'est la solution implémentée en fonction:

Class MyComponent extends React.Component {
   constructor(props) {
      super(props);
      this.state = this.getInitialState();
   }

   getInitialState = () => {
     const initialState = {
        /* state props */
     };
     return initialState;
 }

  resetState = () => {
     this.setState(this.getInitialState());
  }
}
16
Eruz Apodaca

Les solutions qui impliquent de définir this.state directement ne fonctionnent pas pour moi dans React 16, voici donc ce que j'ai fait pour réinitialiser chaque clé:

  const initialState = { example: 'example' }
  ...
  constructor() {
      super()
      this.state = initialState
  }
  ...
  reset() {
    const keys = Object.keys(this.state)
    const stateReset = keys.reduce((acc, v) => ({ ...acc, [v]: undefined }), {})
    this.setState({ ...stateReset, ...initialState })
  }
9

Tout d'abord, vous devez stocker votre état initial lorsque vous utilisez la fonction componentWillMount() à partir du cycle de vie du composant:

componentWillMount() {
    this.initialState = this.state
}

Ceci stocke votre état initial et peut être utilisé pour le réinitialiser à tout moment en appelant

this.setState(this.initialState)
5
Balanced02
const initialState = {
    a: '',
    b: '',
    c: ''
};

class ExampleComponent extends Component {
    state = { ...initialState } // use spread operator to avoid mutation
    handleReset = this.handleReset.bind(this);

    handleReset() {
         this.setState(initialState);
    }
 }

N'oubliez pas que pour pouvoir réinitialiser l'état, il est important de ne pas muter le paramètre initialState. 

state = {...initialState} // GOOD 
// => state points to a new obj in memory which has the values of initialState

state = initialState // BAD 
// => they point to the same obj in memory

Le moyen le plus pratique serait d'utiliser ES6 Spread Operator. Mais vous pouvez également utiliser Object.assign à la place. Ils réaliseraient tous les deux la même chose.

state = Object.assign({}, initialState); // GOOD
state = {...initialState}; // GOOD
3
uke5tar

J'ajouterai à la réponse ci-dessus que la fonction de réinitialisation devrait également attribuer un état comme suit:

reset() {
  this.state = initialState;
  this.setState(initialState);
}

La raison en est que si votre état sélectionne une propriété qui n'était pas dans l'état initial, cette clé/valeur ne sera pas effacée, car setState ne fait que mettre à jour les clés existantes. L'affectation ne suffit pas pour que le composant soit restitué, incluez donc également l'appel setState - vous pourriez même vous en sortir avec this.setState ({}) après l'affectation.

2
Brian Loughnane

Voici comment je le gère:

class MyComponent extends React.Component{
  constructor(props){
    super(props);
    this._initState = {
        a: 1,
        b: 2
      }
    this.state = this._initState;
  }

  _resetState(){
     this.setState(this._initState);
   }
}
2
eveevans

Dans la plupart des cas, vous n'avez pas besoin d'une copie en profondeur, rarement l'état initial est un objet, utilisez donc l'opérateur spread que babel transpile en object.assign devrait convenir. 

Donc, dans le constructeur, vous auriez:

    class MyComponent extends Component {
        constructor(props) {
            super(props)
            this.state = {
                key: value,
                key2: value
            }
            this.initialState = { ...this.state } 
        }
    }

De là, vous pouvez utiliser 

this.setState(this.initialState);

réinitialiser. Mais si, pour une raison quelconque, votre état initial est un objet plus complexe, utilisez une bibliothèque.

0
Goran Jakovljevic

Dans certaines circonstances, il suffit de définir toutes les valeurs de state à null.

Si votre état est mis à jour de telle sorte que vous ne sachiez pas ce qu'il peut contenir, vous voudrez peut-être

this.setState(Object.assign(...Object.keys(this.state).map(k => ({[k]: null}))))

Ce qui va changer l'état comme suit

{foo: 1, bar: 2, spam: "whatever"} > {foo: null, bar: null, spam: null}

Pas une solution dans tous les cas, mais fonctionne bien pour moi.

0
SColvin