setState vs replaceState dans React.js

96

Je suis nouveau dans la bibliothèque React.js et je passais en revue certains des tutoriels et je suis tombé sur:

  • this.setState
  • this.replaceState

La description donnée n'est pas très claire (IMO).

setState is done to 'set' the state of a value, even if its already set 
in the 'getInitialState' function.

De même,

The replaceState() method is for when you want to clear out the values 
already in state, and add new ones.

J'ai essayé this.setState({data: someArray});suivi de this.replaceState({test: someArray});puis console.logged eux et j'ai trouvé que statemaintenant avait à la fois dataet test.

Ensuite, j'ai essayé de les this.setState({data: someArray});suivre this.setState({test: someArray});, puis de les consigner par console et j'ai trouvé que statej'avais à nouveau dataet test.

Alors, quelle est exactement la différence entre les deux?

myusuf
la source
1
Votre premier exemple est inexact. replaceState supprimerait l'état précédent. Vous le testez probablement de manière incorrecte.
Brigand
1
Je ne cherchais pas de changements dans un rappel. C'est peut-être pourquoi ..
myusuf

Réponses:

138

Avec setStateles états actuel et précédent sont fusionnés. Avec replaceState, il jette l'état actuel et le remplace uniquement par ce que vous fournissez. Il setStateest généralement utilisé sauf si vous devez vraiment supprimer des clés pour une raison quelconque; mais les définir sur false / null est généralement une tactique plus explicite.

Bien que cela soit possible, cela pourrait changer; replaceState utilise actuellement l'objet passé comme état, c'est replaceState(x)-à- dire et une fois qu'il est défini this.state === x. C'est un peu plus léger que setState, donc cela pourrait être utilisé comme une optimisation si des milliers de composants définissent fréquemment leur état.
Je l'ai affirmé avec ce cas de test .


Si votre état actuel est {a: 1}, et que vous appelez this.setState({b: 2}); lorsque l'état sera appliqué, il le sera {a: 1, b: 2}. Si vous avez appelé this.replaceState({b: 2})votre état serait {b: 2}.

Remarque: l'état n'est pas défini instantanément, alors ne le faites pas this.setState({b: 1}); console.log(this.state)lors des tests.

Brigand
la source
1
Toujours pas clair pour moi. Pouvez-vous donner un exemple où l'utilisation de l'un sur l'autre change le résultat, c'est-à-dire cette fusion à laquelle vous faites référence ...
Serj Sagan
1
Comment y a-t-il un état antérieur et un état actuel, comme dans, comment pouvons-nous y accéder? De plus, j'ai passé un objet pour remplacer l'état, mais les données d'état précédentes étaient toujours présentes.
myusuf
1
Alors, quand l'état est-il défini? Comme dans quand puis-je console.log et le tester?
myusuf
21
@myusuf.setState({...}, callback)
Brigand
46

Définition par exemple:

// let's say that this.state is {foo: 42}

this.setState({bar: 117})

// this.state is now {foo: 42, bar: 117}

this.setState({foo: 43})

// this.state is now {foo: 43, bar: 117}

this.replaceState({baz: "hello"})

// this.state. is now {baz: "hello"}

Prenez note de ceci dans la documentation , cependant:

setState () ne modifie pas immédiatement this.state mais crée une transition d'état en attente. Accéder à this.state après avoir appelé cette méthode peut potentiellement renvoyer la valeur existante.

De même pour replaceState()

Grav
la source
14

Selon la documentation , replaceStatepourrait devenir obsolète:

Cette méthode n'est pas disponible sur les composants de classe ES6 qui étendent React.Component. Il pourra être entièrement supprimé dans une future version de React.

Liran Brimer
la source
Existe-t-il une méthode de remplacement similaire?
zero_cool
1
Pour une méthode "similaire", vous pouvez utiliser this.setState ({all: undefined, old: undefined, keys: undefined, new: value})
Wren
@Wren, qu'est-ce que c'est? Cette signature officielle est-elle pour réinitialiser l'état?
Vert
Non, il s'agit simplement de définir explicitement l'état préexistant sur undefined, ce qui est le résultat net de "replaceState" sans toutes les clés existantes.
Wren
2

Depuis replaceStateest maintenant obsolète, voici une solution de contournement très simple. Bien qu'il soit probablement assez rare que vous ayez / devriez recourir à cela.

Pour supprimer l'état:

for (const old_key of Object.keys(this.state))
    this.setState({ [old_key]: undefined });

Ou, alternativement, si vous ne voulez pas avoir plusieurs appels vers setState

const new_state = {};
for (const old_key of Object.keys(this.state))
    new_state[old_key] = undefined;
this.setState(new_state);

Essentiellement, toutes les clés précédentes dans l'état retournent maintenant undefined, ce qui peut très facilement être filtré avec une ifinstruction:

if (this.state.some_old_key) {
    // work with key
} else {
    // key is undefined (has been removed)
}

if ( ! this.state.some_old_key) {
    // key is undefined (has been removed)
} else {
    // work with key
}

Dans JSX:

render() {
    return <div>
        { this.state.some_old_key ? "The state remains" : "The state is gone" }
    </div>
}

Enfin, pour "remplacer" l'état, combinez simplement le nouvel objet d'état avec une copie de l'ancien état qui a été undefined, et définissez-le comme état:

const new_state = {new_key1: "value1", new_key2: "value2"};
const state = this.state;

for (const old_key of Object.keys(state))
    state[old_key] = undefined;

for (const new_key of Object.keys(new_state))
    state[new_key] = new_state[new_key];

this.setState(state);
stormpie
la source