setState vs replaceState em React.js

96

Eu sou novo na Biblioteca React.js e estava lendo alguns dos tutoriais e me deparei com:

  • this.setState
  • this.replaceState

A descrição dada não é muito clara (IMO).

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

Similarmente,

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

Tentei this.setState({data: someArray});seguido por this.replaceState({test: someArray});e console.logged eles e descobri que stateagora tinha ambos datae test.

Então, eu tentei this.setState({data: someArray});seguido por this.setState({test: someArray});e console.logged eles e descobri que statenovamente tinha ambos datae test.

Então, qual é exatamente a diferença entre os dois?

myusuf
fonte
1
Seu primeiro exemplo é impreciso. replaceState removeria o estado anterior. Você provavelmente está testando incorretamente.
Brigand
1
Eu não estava procurando por mudanças em um retorno de chamada. Talvez seja por isso ..
myusuf

Respostas:

138

Com setStateos estados atual e anterior são mesclados. Com replaceState, ele elimina o estado atual e o substitui apenas pelo que você fornece. Normalmente setStateé usado, a menos que você realmente precise remover as chaves por algum motivo; mas defini-los como falso / nulo geralmente é uma tática mais explícita.

Embora seja possível, pode mudar; replaceState atualmente usa o objeto passado como o estado, ou seja replaceState(x), uma vez definido this.state === x. Isso é um pouco mais leve do que setState, portanto, poderia ser usado como uma otimização se milhares de componentes configurassem seus estados com frequência.
Eu afirmei isso com este caso de teste .


Se o seu estado atual é {a: 1}, e você liga this.setState({b: 2}); quando o estado for aplicado, será {a: 1, b: 2}. Se você ligasse this.replaceState({b: 2})seu estado seria {b: 2}.

Nota lateral: o estado não é definido instantaneamente, então não faça isso this.setState({b: 1}); console.log(this.state)durante o teste.

Brigand
fonte
1
Ainda não está claro para mim. Você pode dar um exemplo em que usar um sobre o outro altera o resultado, ou seja, essa fusão a que você se refere ...
Serj Sagan
1
Como existe um estado anterior e um estado atual, como em, como podemos acessá-los? Além disso, passei um objeto para substituir o estado, mas os dados de estado anteriores ainda estavam presentes.
myusuf
1
Então, quando o estado é definido? Quando posso fazer o console.log e testá-lo?
myusuf
21
@myusuf.setState({...}, callback)
Brigand
46

Definição por exemplo:

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

Observe isso na documentação :

setState () não altera imediatamente this.state, mas cria uma transição de estado pendente. Acessar this.state após chamar esse método pode potencialmente retornar o valor existente.

O mesmo vale para replaceState()

Grav
fonte
14

De acordo com os documentos , replaceStatepode ficar obsoleto:

Este método não está disponível nos componentes da classe ES6 que estendem React.Component. Ele pode ser removido inteiramente em uma versão futura do React.

Liran Brimer
fonte
Existe um método de substituição semelhante?
zero_cool
1
Para um método "semelhante", você poderia usar this.setState ({all: undefined, old: undefined, keys: undefined, new: value})
Wren
@Wren, o que é isso? Esta assinatura oficial é para redefinir o estado?
Verde
Não, é apenas definir explicitamente o estado pré-existente como indefinido, que é o resultado líquido de "replaceState" sem todas as chaves existentes.
Wren
2

Como replaceStateagora está obsoleto, aqui está uma solução alternativa muito simples. Embora seja provavelmente muito raro você recorrer / deva recorrer a isso.

Para remover o estado:

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

Ou, alternativamente, se você não quiser ter várias chamadas para setState

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

Essencialmente, todas as chaves anteriores no estado agora retornam undefined, que podem ser facilmente filtradas com uma ifinstrução:

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
}

Em JSX:

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

Finalmente, para "substituir" o estado, basta combinar o novo objeto de estado com uma cópia do antigo estado que foi undefinede defini-lo 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);
torta de tempestade
fonte