setState vs replaceState w React.js

96

Jestem nowy w bibliotece React.js i przeglądałem kilka samouczków i natknąłem się na:

  • this.setState
  • this.replaceState

Podany opis nie jest zbyt jasny (IMO).

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

Podobnie,

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

Próbowałem je this.setState({data: someArray});śledzić, this.replaceState({test: someArray});a następnie console.logged je i stwierdziłem, że stateteraz mam zarówno datai test.

Następnie spróbowałem this.setState({data: someArray});śledzić je, this.setState({test: someArray});a następnie console.logged je i stwierdziłem, że stateznowu mam oba datai test.

Więc jaka dokładnie jest różnica między tymi dwoma?

myusuf
źródło
1
Twój pierwszy przykład jest niedokładny. replaceState usunie poprzedni stan. Prawdopodobnie testujesz to niepoprawnie.
Brigand
1
Nie szukałem zmian w oddzwonieniu. Może dlatego…
myusuf

Odpowiedzi:

138

Z setStateobecnym i poprzednim stanem są łączone. W programie replaceStatewyrzuca bieżący stan i zastępuje go tylko tym, co podasz. Zwykle setStatejest używany, chyba że naprawdę musisz z jakiegoś powodu usunąć klucze; ale ustawienie ich na false / null jest zwykle bardziej wyraźną taktyką.

Chociaż jest możliwe, może się to zmienić; replaceState obecnie używa obiektu przekazanego jako stan, tj. replaceState(x)po jego ustawieniu this.state === x. Jest to trochę lżejsze niż setState, więc może być używane jako optymalizacja, jeśli tysiące komponentów często ustawiają swoje stany.
Potwierdziłem to w tym przypadku testowym .


Jeśli twój obecny stan to {a: 1}i dzwonisz this.setState({b: 2}); kiedy stan zostanie zastosowany, będzie {a: 1, b: 2}. Gdybyś zadzwonił, this.replaceState({b: 2})twój stan byłby {b: 2}.

Uwaga dodatkowa: stan nie jest ustawiany natychmiast, więc nie rób tego this.setState({b: 1}); console.log(this.state)podczas testowania.

Bandyta
źródło
1
Wciąż niejasne dla mnie. Czy możesz podać przykład, w którym użycie jednego nad drugim zmienia wynik, tj. To scalanie, do którego się odnosisz ...
Serj Sagan
1
W jaki sposób istnieje poprzedni stan i stan obecny, jak w, jak możemy uzyskać do nich dostęp? Przekazałem również obiekt, aby zastąpić stan, ale dane o poprzednim stanie były nadal obecne.
myusuf
1
Więc kiedy jest ustawiony stan? Kiedy mogę go console.logować i przetestować?
myusuf
21
@myusuf.setState({...}, callback)
Brigand
46

Definicja na podstawie przykładu:

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

Zwróć jednak uwagę na to z dokumentacji :

setState () nie zmienia natychmiast this.state, ale tworzy oczekującą zmianę stanu. Dostęp do this.state po wywołaniu tej metody może potencjalnie zwrócić istniejącą wartość.

To samo dotyczy replaceState()

Grav
źródło
14

Zgodnie z docs , replaceStatemoże się nieaktualne:

Ta metoda nie jest dostępna w przypadku komponentów klasy ES6, które rozszerzają React.Component. Może zostać całkowicie usunięty w przyszłej wersji React.

Liran Brimer
źródło
Czy istnieje podobna metoda wymiany?
zero_cool
1
W przypadku „podobnej” metody można użyć this.setState ({all: undefined, old: undefined, keys: undefined, new: value})
Wren
@Wren, co to jest? Czy ten oficjalny podpis resetuje stan?
Green
Nie, po prostu jawnie ustawia istniejący stan na niezdefiniowany, co jest wynikiem netto operacji „replaceState” bez wszystkich istniejących kluczy.
Wren
2

Ponieważ replaceStatejest teraz przestarzały, tutaj jest bardzo proste obejście. Chociaż prawdopodobnie rzadko zdarza się / powinieneś uciekać się do tego.

Aby usunąć stan:

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

Lub, jeśli nie chcesz mieć wielu połączeń do setState

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

Zasadniczo wszystkie poprzednie klucze w stanie teraz zwracają się undefined, co można bardzo łatwo przefiltrować za pomocą ifinstrukcji:

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
}

W JSX:

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

Na koniec, aby „zastąpić” stan, po prostu połącz nowy obiekt stanu z kopią poprzedniego stanu undefinedi ustaw go jako stan:

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);
burza
źródło