setState vs replaceState en React.js

96

Soy nuevo en la biblioteca React.js y estaba repasando algunos de los tutoriales y me encontré con:

  • this.setState
  • this.replaceState

La descripción dada no es muy clara (IMO).

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

Similar,

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

Intenté this.setState({data: someArray});seguido de this.replaceState({test: someArray});y luego console.logé y descubrí que stateahora tenía ambos datay test.

Luego, lo intenté this.setState({data: someArray});seguido de this.setState({test: someArray});y luego console.logé y encontré que statenuevamente tenía ambos datay test.

Entonces, ¿cuál es exactamente la diferencia entre los dos?

myusuf
fuente
1
Tu primer ejemplo es inexacto. replaceState eliminaría el estado anterior. Probablemente lo esté probando incorrectamente.
Brigand
1
No estaba buscando cambios en una devolución de llamada. Quizás por eso ..
myusuf

Respuestas:

138

Con setStatelos estados actual y anterior se fusionan. Con replaceState, descarta el estado actual y lo reemplaza solo con lo que usted proporciona. Por setStatelo general, se usa a menos que realmente necesite eliminar claves por alguna razón; pero establecerlos en falso / nulo suele ser una táctica más explícita.

Si bien es posible, podría cambiar; replaceState actualmente usa el objeto pasado como estado, es decir replaceState(x), y una vez que se establece this.state === x. Esto es un poco más ligero que setState, por lo que podría usarse como optimización si miles de componentes establecen sus estados con frecuencia.
Afirmé esto con este caso de prueba .


Si su estado actual es {a: 1}, y llama this.setState({b: 2}); cuando se aplique el estado, lo será {a: 1, b: 2}. Si llama a this.replaceState({b: 2})su estado sería {b: 2}.

Nota al margen: el estado no se establece instantáneamente, así que no lo haga this.setState({b: 1}); console.log(this.state)al realizar la prueba.

Bandido
fuente
1
Aún no me queda claro. ¿Puede dar un ejemplo en el que el uso de uno sobre el otro cambia el resultado, es decir, esta fusión a la que se refiere ...
Serj Sagan
1
¿Cómo hay un estado anterior y un estado actual, como en, cómo podemos acceder a ellos? Además, pasé un objeto para reemplazar el estado, pero aún así, los datos del estado anterior todavía estaban presentes.
myusuf
1
Entonces, ¿cuándo se establece el estado? ¿Cuándo puedo console.log y probarlo?
myusuf
21
@myusuf.setState({...}, callback)
Brigand
46

Definición por ejemplo:

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

Sin embargo, tome nota de esto de los documentos :

setState () no muta inmediatamente this.state pero crea una transición de estado pendiente. Acceder a this.state después de llamar a este método puede devolver potencialmente el valor existente.

Lo mismo vale para replaceState()

Grav
fuente
14

Según los documentos , replaceStatepodría quedar obsoleto:

Este método no está disponible en los componentes de la clase ES6 que amplían React.Component. Puede eliminarse por completo en una versión futura de React.

Liran Brimer
fuente
¿Existe un método de reemplazo similar?
zero_cool
1
Para un método "similar", podría usar this.setState ({all: undefined, old: undefined, keys: undefined, new: value})
Wren
@Wren, ¿qué es esto? ¿Esta firma oficial es para restablecer el estado?
Verde
No, simplemente establece explícitamente el estado preexistente en indefinido, que es el resultado neto de "replaceState" sin todas las claves existentes.
Wren
2

Dado replaceStateque ahora está en desuso, aquí hay una solución muy simple. Aunque probablemente es muy raro que recurra a necesitar esto.

Para eliminar el estado:

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

O, alternativamente, si no desea tener varias llamadas a setState

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

Esencialmente, todas las claves anteriores en el estado ahora regresan undefined, que se pueden filtrar muy fácilmente con una ifdeclaración:

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
}

En JSX:

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

Finalmente, para "reemplazar" el estado, simplemente combine el nuevo objeto de estado con una copia del estado anterior undefinedy configúrelo como estado:

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);
tormenta
fuente