Я пытаюсь организовать свое состояние с помощью вложенного свойства следующим образом:
this.state = {
someProperty: {
flag:true
}
}
Но обновление состояния, как это,
this.setState({ someProperty.flag: false });
не работает Как это можно сделать правильно?
javascript
reactjs
ecmascript-6
setstate
Алекс Йонг
источник
источник
Ответы:
Для того, чтобы
setState
использовать вложенный объект, вы можете следовать приведенному ниже подходу, так как я думаю, что setState не обрабатывает вложенные обновления.Идея состоит в том, чтобы создать фиктивный объект, выполнить над ним операции, а затем заменить состояние компонента на обновленный объект.
Теперь оператор распространения создает только одну вложенную копию объекта уровня. Если ваше состояние сильно вложено, как:
Вы можете установить состояние с использованием оператора распространения на каждом уровне, как
Однако приведенный выше синтаксис становится все более уродливым, так как состояние становится все более и более вложенным, и поэтому я рекомендую вам использовать
immutability-helper
package для обновления состояния.Смотрите этот ответ о том, как обновить состояние с
immutability helper
.источник
someProperty
и мы изменяем этоthis.setState((prevState) => ({nested: {...prevState.nested, propertyToSet: newValue}})
немного утомительно, хотя ......prevState,
в последнем примере, только выsomeProperty
и его детиНаписать в одну строку
источник
this.state
сразу послеsetState
и ожидайте, что это будет иметь новое значение. Против вызоваthis.state
внутриsetState
. Или есть проблема с последним, которая мне не ясна?this.state
послеsetState
. Кроме того, мы не переходимthis.state
кsetState
. В…
раскинутые оператор свойства. Это то же самое, что Object.assign (). github.com/tc39/proposal-object-rest-spreadthis.setState(currentState => { someProperty: { ...currentState.someProperty, flag: false} });
может позволить избежать этой проблемы?Иногда прямые ответы не самые лучшие :)
Укороченная версия:
этот код
должно быть упрощено как-то вроде
Длинная версия:
В настоящее время вы не должны работать с вложенным состоянием в React . Потому что React не ориентирован на работу с вложенными состояниями и все предлагаемые здесь решения выглядят как хаки. Они не используют рамки, но борются с ней. Они предлагают написать не очень понятный код для сомнительной цели группировки некоторых свойств. Поэтому они очень интересны как ответ на вызов, но практически бесполезны.
Давайте представим следующее состояние:
Что произойдет, если вы измените только значение
child1
? React не будет повторно отображать представление, поскольку использует поверхностное сравнение и обнаружит, чтоparent
свойство не изменилось. Кстати, мутирование государственного объекта напрямую считается плохой практикой в целом.Так что вам нужно заново создать весь
parent
объект. Но в этом случае мы столкнемся с другой проблемой. Реакт будет думать, что все дети изменили свои ценности, и сделает все заново. Конечно, это не хорошо для производительности.Эту проблему еще можно решить, написав некоторую сложную логику,
shouldComponentUpdate()
но я бы предпочел остановиться здесь и использовать простое решение из короткой версии.источник
отказ
ответ на ваши страдания - см. пример здесь
Существует еще один более короткий способ обновления любого вложенного свойства.
На одной линии
примечание: здесь это оператор запятой ~ MDN , посмотрите его в действии (песочница) .
Это похоже на (хотя это не меняет ссылку на состояние)
Для тонкой разницы в этом контексте между
forceUpdate
иsetState
посмотрите связанный пример.Конечно, это злоупотребление некоторыми основными принципами, так как они
state
должны быть доступны только для чтения, но, поскольку вы немедленно отбрасываете старое состояние и заменяете его новым, это вполне нормально.Предупреждение
Даже если компонент, содержащий состояние, будет обновляться и перерисовываться должным образом ( кроме этой ошибки ) , реквизиты не смогут распространяться на детей (см. Комментарий Spymaster ниже) . Используйте эту технику, только если вы знаете, что делаете.
Например, вы можете передать измененную плоскую подпорку, которая обновляется и легко передается.
Теперь, даже если ссылка для complexNestedProp не изменилась ( shouldComponentUpdate )
компонент будет засавить всякий раз , когда обновления родительского компонента, который является случаем после вызова
this.setState
илиthis.forceUpdate
в родительском.Эффекты мутирования государства
Использование вложенного состояния и мутирует состояние непосредственно опасно , потому что разные объекты могут держать (намеренно или нет) разные (старые) ссылки на состояние и не обязательно знать , когда обновление (при использовании, например ,
PureComponent
или , еслиshouldComponentUpdate
осуществляется для возвратаfalse
) или являются предназначен для отображения старых данных, как в примере ниже.В любом случае здесь вы можете увидеть, что
Nested PureChildClass
он не рендерится из-за того, что реквизит не распространяется.источник
state
и использует настраиваемые наблюдаемые свойства. React -setState
это просто встроенное удобство, но вы скоро поймете, что оно имеет свои пределы. Использование пользовательских свойств и интеллектуальное использованиеforceUpdate
дает вам гораздо больше. Используйте Observables вместо состояния в компонентах React.this.forceUpdate()
или реализовывать определенныеshouldComponentUpdate
.Если вы используете ES2015, у вас есть доступ к Object.assign. Вы можете использовать его следующим образом для обновления вложенного объекта.
Вы объединяете обновленные свойства с существующими и используете возвращенный объект для обновления состояния.
Редактировать: Добавлен пустой объект в качестве цели в функцию назначения, чтобы убедиться, что состояние не изменено напрямую, как указывал carkod.
источник
источник
property
объект содержит несколько вложенных свойств, первое удалит их, второе - нет. codesandbox.io/s/nameless-pine-42thuЕсть много библиотек, чтобы помочь с этим. Например, используя immutability-helper :
Используя набор lodash / fp :
Использование lodash / fp merge:
источник
lodash
, вы, вероятно, захотите попробовать_.cloneDeep
установить состояние клонированной копии.lodash/fp
, поэтому нам не нужно беспокоиться о мутациях.merge
илиset
функций в lodash / fp помимо синтаксиса?this.setState(newState)
методы lodash / fp. Другой недостаток заключается в том, что у lodash.set
(non-fp) есть другой порядок аргументов, который на некоторое время сбил меня с толку .Мы используем Immer https://github.com/mweststrate/immer для решения подобных проблем.
Просто заменили этот код в одном из наших компонентов
С этим
С immer вы обрабатываете свое состояние как «нормальный объект». Магия происходит за сценой с прокси-объектами.
источник
Вот вариант первого ответа, приведенного в этой теме, который не требует никаких дополнительных пакетов, библиотек или специальных функций.
Чтобы установить состояние определенного вложенного поля, вы задали весь объект. Я сделал это, создав переменную,
newState
и распространение содержимого текущего состояния в него первым использованием ES2015 оператора распространения . Затем я заменил значениеthis.state.flag
на новое (так как я установилflag: value
после распространения текущего состояния в объект,flag
поле в текущем состоянии переопределяется). Затем я просто устанавливаю состояниеsomeProperty
моегоnewState
объекта.источник
Хотя на самом деле вложение - это не то, как следует обращаться с состоянием компонента, иногда для чего-то более простого для одноуровневого вложения.
Для такого государства
Повторно используемый метод, который я использовал, выглядел бы так.
затем просто передавая имя объекта для каждого вложения, к которому вы хотите обратиться ...
источник
Я использовал это решение.
Если у вас есть вложенное состояние, подобное этому:
Вы можете объявить функцию handleChange, которая копирует текущее состояние и переназначает его с измененными значениями.
здесь HTML с прослушивателем событий
источник
Создайте копию состояния:
внести изменения в этот объект:
сейчас обновите состояние
источник
Хотя вы спрашивали о состоянии компонента React на основе классов, такая же проблема существует с ловушкой useState. Еще хуже: ловушка useState не принимает частичные обновления. Так что этот вопрос стал очень актуальным, когда был введен хук useState.
Я решил опубликовать следующий ответ, чтобы убедиться, что этот вопрос охватывает более современные сценарии, в которых используется хук useState:
Если у вас есть:
Вы можете установить вложенное свойство путем клонирования текущего и исправления необходимых сегментов данных, например:
Или вы можете использовать библиотеку Immer, чтобы упростить клонирование и исправление объекта.
Или вы можете использовать библиотеку Hookstate (отказ от ответственности: я автор), чтобы просто полностью управлять сложными (локальными и глобальными) данными состояния и повысить производительность (читай: не беспокоиться об оптимизации рендеринга):
получить поле для рендеринга:
установить вложенное поле:
Вот пример Hookstate, где состояние глубоко / рекурсивно вложено в древовидную структуру данных .
источник
Два других варианта еще не упомянуты:
источник
Чтобы сделать вещи общими, я работал над ответами @ ShubhamKhatri's и @ Qwerty.
государственный объект
элементы управления вводом
метод updateState
setState как ответ @ ShubhamKhatri
setState как ответ @ Qwerty
Примечание. Эти методы не работают для массивов.
источник
Я очень серьезно отношусь к проблемам, уже высказанным в связи с созданием полной копии состояния вашего компонента. С учетом сказанного, я настоятельно рекомендую Immer .
Это должно сработать
React.PureComponent
(например, сравнение с неглубокими состояниями с помощью React), так какImmer
умно использует прокси-объект для эффективного копирования произвольно глубокого дерева состояний. Immer также более безопасен по сравнению с такими библиотеками, как Immutability Helper, и идеально подходит для пользователей Javascript и Typescript.Полезность Typescript
источник
источник
obj
это просто ссылка на состояние, поэтому через него вы мутируете фактическийthis.state
объектЯ нашел, что это работает для меня, имея форму проекта в моем случае, где, например, у вас есть идентификатор и имя, и я бы предпочел поддерживать состояние для вложенного проекта.
Дай мне знать!
источник
Нечто подобное может быть достаточно,
источник
Я знаю, что это старый вопрос, но все же хотел поделиться тем, как я этого добился. Предполагая, что состояние в конструкторе выглядит так:
Моя
handleChange
функция такая:И убедитесь, что вы называете входные данные соответственно:
источник
Я делаю вложенные обновления с сокращенным поиском:
Пример:
Вложенные переменные в состоянии:
Функция:
Использование:
источник
Это мой initialState
Хук или вы можете заменить его на состояние (компонент класса)
Метод для handleChange
Метод для установки состояния с вложенными состояниями
Наконец, это вход, который я использую
источник
Если вы используете formik в своем проекте, у него есть простой способ справиться с этим. Вот самый простой способ сделать это с formik.
Сначала установите ваши начальные значения в атрибуте formik initivalues или в реакции. штат
Здесь начальные значения определены в состоянии реакции.
определите выше initialValues для поля formik внутри
initiValues
атрибута formikСоздайте консоль для проверки обновленного состояния
string
вместо функцииboolean
formik,setFieldValue
чтобы установить состояние, или воспользуйтесь инструментом отладчика реакции, чтобы увидеть изменения в значениях состояния formik.источник
попробуйте этот код:
источник
someProperty
и после выполнения вышеуказанного кодаflag
останется только свойствоя видел следующее в книге:
но я не уверен, правильно ли это ..
источник