setState против replaceState в React.js

96

Я новичок в библиотеке React.js, просматривал некоторые учебники и наткнулся на:

  • this.setState
  • this.replaceState

Приведенное описание не очень четкое (ИМО).

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

Так же,

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

Я попробовал this.setState({data: someArray});следовать за, this.replaceState({test: someArray});а затем console.logged их, и я обнаружил, что stateтеперь есть и dataи test.

Затем я попробовал this.setState({data: someArray});следовать за ними, this.setState({test: someArray});а затем console.logged их, и я обнаружил, что stateснова были оба dataи test.

Итак, в чем именно разница между ними?

Мюсуф
источник
1
Ваш первый пример неточен. replaceState удалит предыдущее состояние. Скорее всего, вы неправильно его тестируете.
Brigand
1
Я не искал изменений в обратном вызове. Может быть поэтому ..
myusuf

Ответы:

138

При setStateэтом текущее и предыдущее состояния объединяются. С replaceStateон выбрасывает текущее состояние и заменяет его только тем, что вы предоставили. Обычно setStateиспользуется, если вам действительно не нужно удалять ключи по какой-либо причине; но установка их на false / null обычно является более явной тактикой.

Хотя возможно, это могло измениться; replaceState в настоящее время использует объект, переданный как состояние, т. е. replaceState(x)и когда он установлен this.state === x. Это немного легче setState, поэтому его можно использовать в качестве оптимизации, если тысячи компонентов часто устанавливают свои состояния.
Я подтвердил это с помощью этого тестового примера .


Если ваше текущее состояние {a: 1}, и вы звоните this.setState({b: 2}); когда применяется состояние, так и будет {a: 1, b: 2}. Если бы вы назвали this.replaceState({b: 2})ваше состояние, было бы {b: 2}.

Боковое примечание: состояние не устанавливается мгновенно, поэтому не делайте этого this.setState({b: 1}); console.log(this.state)при тестировании.

Разбойник
источник
1
Мне все еще непонятно. Можете ли вы привести пример, когда использование одного над другим изменяет результат, то есть это слияние, о котором вы говорите ...
Серж Саган
1
Как там предыдущее состояние и текущее состояние, например, как мы можем получить к ним доступ? Кроме того, я передал объект для замены состояния, но все же предыдущие данные о состоянии все еще присутствовали.
myusuf
1
Итак, когда устанавливается состояние? Когда я могу console.log это проверить?
myusuf
21
@myusuf.setState({...}, callback)
Brigand
46

Определение на примере:

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

Однако обратите внимание на это в документации :

setState () не изменяет немедленно this.state, но создает отложенный переход состояния. Доступ к this.state после вызова этого метода потенциально может вернуть существующее значение.

То же самое касается replaceState()

Грав
источник
14

Согласно документации , replaceStateможет устареть:

Этот метод недоступен для компонентов класса ES6, расширяющих React.Component. Он может быть полностью удален в будущей версии React.

Лиран Браймер
источник
Есть ли аналогичный способ замены?
zero_cool
1
Для «похожего» метода вы можете использовать this.setState ({all: undefined, old: undefined, keys: undefined, new: value})
Рен
@ Рен, что это? Это официальная подпись для сброса состояния?
Green
Нет, он просто явно устанавливает для существующего состояния значение undefined, что является чистым результатом «replaceState» без всех существующих ключей.
Wren
2

Поскольку replaceStateтеперь не рекомендуется, вот очень простой обходной путь. Хотя, вероятно, довольно редко вы будете / должны прибегать к этому.

Чтобы удалить состояние:

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

Или, в качестве альтернативы, если вы не хотите, чтобы несколько вызовов setState

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

По сути, все предыдущие ключи в состоянии теперь возвращаются undefined, что очень легко можно отфильтровать с помощью ifоператора:

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
}

В JSX:

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

Наконец, чтобы «заменить» состояние, просто объедините новый объект состояния с копией старого состояния, которое было undefined, и установите его как состояние:

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);
штурмовик
источник