Реагируйте: как обновить state.item [1] в состоянии с помощью setState?

Какой из них подходит для вашего проекта?

Если вы не хотите или можете использовать внешние зависимости и иметь простую структуру состояний , придерживайтесь Object.assign .

Если вы манипулируете огромным и / или сложным состоянием , cloneDeep от cloneDeep — мудрый выбор.

Если вам нужны расширенные возможности , то есть, если ваша структура состояний сложная и вам нужно выполнять все виды операций над ней, попробуйте immutability-helper , это очень продвинутый инструмент, который можно использовать для манипулирования состоянием.

Если вы храните сложные данные в состоянии React, возможно, сейчас самое время подумать о других способах обработки этих данных. Установка сложного состояния в React не является простой операцией, и я настоятельно рекомендую подумать о разных подходах.

Скорее всего, вам лучше не хранить свои сложные данные в хранилище Redux, устанавливать их там с помощью редукторов и / или саг и обращаться к ним с помощью селекторов.

Примечания стороны

Опять же, имейте в виду, что this.setState() изменяет только свойства первого уровня объекта состояния (в данном случае это свойство foo ), а не глубоко вложенные ( foo.bar ). Если бы он вел себя по-другому, этот вопрос не существовал бы.

И, кстати, this.setState({ foo }) — это просто сокращение для this.setState({ foo: foo }) . И () ={amp}gt; { console.log(this.state.foo.bar) } сразу после { foo } обратного вызова, который выполняется сразу после того, как setState установил состояние.

1. Ванильный JavaScript Object.assign

 (...essential imports) class App extends Component { state = { foo: { bar: 'initial value' } } componentDidMount() { console.log(this.state.foo.bar) // initial value const foo = Object.assign({}, this.state.foo, { bar: 'further value' }) console.log(this.state.foo.bar) // initial value this.setState({ foo }, () ={amp}gt; { console.log(this.state.foo.bar) // further value }) } (...rest of code) 

Имейте в виду, что Object.assign не будет выполнять глубокое клонирование , поскольку он только копирует значения свойств , и поэтому то, что он делает, называется поверхностным копированием (см. Комментарии).

Чтобы это работало, мы должны манипулировать только объектами верхнего уровня этого объекта ( state.foo ). И их значения ( state.foo.bar ) должны быть примитивными (строки, числа, логические значения).

В этом примере мы создаем новую константу ( const foo... ), используя Object.assign , который создает пустой объект ( {} ), копирует объект state.foo ( { bar:

‘начальное значение’}) в него, а затем копирует другой объект { bar: 'further value' } поверх него. Итак, в конце концов, вновь созданная константа foo будет содержать значение { bar:

‘дополнительная ценность’}, так как свойство bar было переопределено. Это foo — совершенно новый объект, который не связан с объектом состояния, поэтому его можно изменять по мере необходимости, и состояние не изменится.

Последняя часть заключается в использовании setState() setter для замены исходного состояния state.foo в состоянии на вновь созданный объект foo .

Теперь представьте, что у нас есть более глубокое состояние, например, state = { foo: { bar: { baz: 'initial value' } } } . Мы могли бы попытаться создать новый объект foo и заполнить его содержимым foo из состояния, но Object.

assign не сможет скопировать значение baz в этот вновь созданный объект foo так как baz вложен слишком глубоко. Вы все еще можете скопировать bar , как в примере выше, но, поскольку это объект сейчас, а не примитив, ссылка из state.foo.

Вместо этого будет скопирована строка bar, что означает, что мы получим локальный объект foo напрямую связанный с состоянием. Это означает, что в этом случае любые мутации локально созданного foo будут влиять на объект state.foo , поскольку они фактически указывают на одно и то же.

Поэтому Object.assign будет работать только в том случае, если у вас есть относительно простая одноуровневая структура с глубоким состоянием, в которой самые внутренние члены содержат значения примитивного типа.

Если у вас есть более глубокие объекты (2-й уровень или более), которые вы должны обновить, не используйте Object.assign . Вы рискуете мутировать государство напрямую.

2. Клон Лодаша Глубокий

 (...essential imports) import cloneDeep from 'lodash.clonedeep' class App extends Component { state = { foo: { bar: 'initial value' } } componentDidMount() { console.log(this.state.foo.bar) // initial value const foo = cloneDeep(this.state.foo) foo.bar = 'further value' console.log(this.state.foo.bar) // initial value this.setState({ foo }, () ={amp}gt; { console.log(this.state.foo.bar) // further value }) } (...rest of code) 

CloneDeep от Lodash более прост в использовании. Он выполняет глубокое клонирование , поэтому это надежный вариант, если у вас достаточно сложное состояние с многоуровневыми объектами или массивами внутри.

3. неизменяемость-помощник

 (...essential imports) import update from 'immutability-helper' class App extends Component { state = { foo: { bar: 'initial value' } }; componentDidMount() { console.log(this.state.foo.bar) // initial value const foo = update(this.state.foo, { bar: { $set: 'further value' } }) console.log(this.state.foo.bar) // initial value this.setState({ foo }, () ={amp}gt; { console.log(this.state.foo.bar) // further value }); } (...rest of code) 

immutability-helper выводит его на совершенно новый уровень, и самое интересное в этом то, что он может не только $set значения $set для элементов состояния, но и $push , $splice , $merge (и т. д.). Вот список доступных команд .

Понравилась статья? Поделиться с друзьями:
JavaScript & TypeScript
Adblock
detector