У меня есть следующее состояние:
this.setState({ selected: { id: 1, name: 'Foobar' } });
Затем я обновляю состояние:
this.setState({ selected: { name: 'Barfoo' }});
Поскольку setState
предполагается слияние, я ожидаю, что это будет:
{ selected: { id: 1, name: 'Barfoo' } };
Но вместо этого он ест идентификатор и состояние:
{ selected: { name: 'Barfoo' } };
Это ожидаемое поведение и каково решение для обновления только одного свойства вложенного объекта состояния?
источник
this.setState({ selected: { ...this.state.selected, name: 'barfoo' } })
что переводится наthis.setState({ selected: _extends({}, this.state.selected, { name: 'barfoo' }) });
underscore
/lodash
. Выделите это в свой ответ, пожалуйста.this.state
не обязательно в актуальном состоянии . Вы можете получить неожиданные результаты, используя метод расширения. Передача функции обновленияsetState
является правильным решением.Помощники неизменности были недавно добавлены в React.addons, поэтому теперь вы можете делать что-то вроде:
Документация помощников по неизменности .
источник
React.addons.update()
метод устарел, но библиотека замены github.com/kolodny/immutability-helper содержит эквивалентнуюupdate()
функцию.Поскольку многие ответы используют текущее состояние в качестве основы для объединения новых данных, я хотел бы отметить, что это может сломаться. Изменения состояния ставятся в очередь и не сразу изменяют объект состояния компонента. Поэтому ссылка на данные состояния до обработки очереди даст вам устаревшие данные, которые не отражают ожидающие изменения, сделанные вами в setState. Из документов:
Это означает, что использование «текущего» состояния в качестве ссылки в последующих вызовах setState ненадежно. Например:
Если вам нужно использовать текущее состояние (например, для объединения данных во вложенный объект), setState альтернативно принимает функцию в качестве аргумента вместо объекта; функция вызывается после любых предыдущих обновлений состояния и передает состояние в качестве аргумента - так что это может быть использовано для внесения атомарных изменений, гарантирующих уважение предыдущих изменений.
источник
this.state
, которое может быть устаревшим (или, скорее, в ожидании обновления в очереди), когда вы обращаетесь к нему.Я не хотел устанавливать другую библиотеку, так что вот еще одно решение.
Вместо того:
Сделайте это вместо этого:
Или, благодаря @ icc97 в комментариях, еще более лаконично, но, возможно, менее читабельно:
Кроме того, чтобы быть ясным, этот ответ не нарушает ни одну из проблем, упомянутых @bgannonpl выше.
источник
this.setState({ selected: Object.assign(this.state.selected, { name: "Barfoo" }));
Object.assign(a, b)
принимает атрибутыb
, вставляет / перезаписывает их,a
а затем возвращаетa
. Реагировать на людей можно, если вы измените состояние напрямую.{}
качестве первого аргумента:this.setState({ selected: Object.assign({}, this.state.selected, { name: "Barfoo" }) });
. Это не изменяет исходное состояние.Сохранение предыдущего состояния на основе ответа @bgannonpl:
Пример Лодаша :
Чтобы убедиться, что все работает правильно, вы можете использовать функцию обратного вызова второго параметра:
Я использовал,
merge
потому чтоextend
что иначе отбрасывает другие свойства.Приведите пример неизменности :
источник
Мое решение для такой ситуации заключается в использовании, как указано в другом ответе, помощников по неизменности .
Поскольку установка состояния в глубину - обычная ситуация, я создал следующий миксин:
Этот миксин входит в большинство моих компонентов, и я обычно не использую
setState
напрямую.С этим миксином все, что вам нужно сделать для достижения желаемого эффекта, это вызвать функцию
setStateinDepth
следующим образом:Чтобы получить больше информации:
setStateinDepth
просмотра документации Immutability Helpers .источник
this.state.test.two
все еще будет там после того, как вы обновитеthis.state.test.one
с помощьюsetStateInDepth({test: {one: {$set: 'new-value'}}})
. Я использую этот код во всех своих компонентах, чтобы обойти ограниченнуюsetState
функцию React .this.state.test
как массив. Перейдя на Объекты, решил это.Я использую классы es6, и в конечном итоге у меня появилось несколько сложных объектов в верхнем состоянии, и я пытался сделать мой основной компонент более модульным, поэтому я создал простую оболочку класса, чтобы сохранить состояние верхнего компонента, но с учетом большей локальной логики. ,
Класс-оболочка принимает в качестве конструктора функцию, которая устанавливает свойство основного состояния компонента.
Затем для каждого сложного свойства в верхнем состоянии я создаю один класс StateWrapped. Здесь вы можете установить реквизиты по умолчанию в конструкторе, и они будут установлены при инициализации класса, вы можете обратиться к локальному состоянию для значений и установить локальное состояние, обратиться к локальным функциям и передать их по цепочке:
Тогда моему компоненту верхнего уровня просто нужен конструктор, чтобы установить для каждого класса его свойство состояния верхнего уровня, простую визуализацию и любые функции, которые взаимодействуют между компонентами.
Кажется, для моих целей это работает достаточно хорошо, имейте в виду, что вы не можете изменить состояние свойств, которые вы назначаете для упакованных компонентов на компоненте верхнего уровня, так как каждый упакованный компонент отслеживает свое собственное состояние, но обновляет состояние на верхнем компоненте каждый раз это меняется.
источник
На данный момент,
согласно документации https://reactjs.org/docs/react-component.html#setstate , используя:
источник
Решение
Изменить: Это решение используется для использования синтаксиса распространения . Цель состояла в том, чтобы сделать объект без каких-либо ссылок на него
prevState
, чтобыprevState
его нельзя было изменить. Но в моем использовании,prevState
казалось, был изменен иногда. Итак, для идеального клонирования без побочных эффектов мы теперь конвертируемprevState
в JSON, а затем снова. (Вдохновение использовать JSON пришло из MDN .)Помните:
setState(prevState => stateChange)
меры
state
том , что вы хотите изменитьШаги 3 и 4 можно объединить в одну строку.
пример
Упрощенный пример:
Это хорошо следует рекомендациям React. На основании ответа eicksl на аналогичный вопрос.
источник
Решение ES6
Мы устанавливаем государство изначально
Мы изменяем свойство на некотором уровне объекта состояния:
источник
React state не выполняет рекурсивное слияние, в
setState
то время как ожидает, что в то же время не будет обновлений на месте. Вы должны либо скопировать вложенные объекты / массивы самостоятельно (с помощью array.slice или Object.assign), либо использовать выделенную библиотеку.Как этот. NestedLink напрямую поддерживает обработку составного состояния React.
Кроме того, ссылка на
selected
илиselected.name
может быть передана повсеместно в виде единого реквизита и изменена там с помощьюset
.источник
Вы установили начальное состояние?
Я буду использовать мой собственный код, например:
В приложении, над которым я работаю, это то, как я устанавливал и использовал состояние. Я верю, что
setState
вы можете просто отредактировать все состояния, которые вы хотите индивидуально, как я это называю, так:Имейте в виду, что вы должны установить состояние в
React.createClass
функции, которую вы вызвалиgetInitialState
источник
Я использую переменную tmp для изменения.
источник
let original = {a:1}; let tmp = original; tmp.a = 5; // original is now === Object {a: 5}
Не делайте этого, даже если это еще не доставило вам проблем.