2014-11-24 3 views
45

Возможно ли сохранить объект в состоянии компонента React? Если да, то как мы можем изменить значение ключа в этом объекте, используя setState? Я думаю, что его не синтаксически разрешено писать что-то вроде this.setState({ abc.xyz: 'new value' }); В подобных строках у меня есть другой вопрос: можно ли иметь набор переменных в компоненте React, чтобы они могли использоваться в любом методе компонента, а не храня их в состоянии? Вы можете создать простой объект, который содержит все эти переменные и поместить его на уровне компонента, точно так же, как вы объявляете какие-либо методы в компоненте. Вероятно, он столкнется с ситуациями, когда вы включаете в свой код много бизнес-логики, и для этого требуется использование многих переменных, значения которых изменяются несколькими методами, и затем вы изменяете состояние компонента на основе этих значений. Таким образом, вместо того, чтобы хранить все эти переменные в состоянии, вы сохраняете только те переменные, значения которых должны быть непосредственно отражены в пользовательском интерфейсе. Если этот подход лучше первого вопроса, который я написал здесь, тогда мне не нужно хранить объект в состоянии.Сохранение объекта в состоянии компонента React?

ответ

28

В дополнение к сообщению Кирана, есть update helper (ранее a react addon). Это может быть установлено с помощью NPM npm install immutability-helper

import update from 'immutability-helper'; 

var abc = update(this.state.abc, { 
    xyz: {$set: 'foo'} 
}); 

this.setState({abc: abc}); 

Это создает новый объект с обновленным значением, и другие свойства остаются неизменными. Это более полезно, когда вам нужно делать такие вещи, как нажимать на массив и одновременно устанавливать другое значение. Некоторые люди используют его везде, потому что он обеспечивает неизменность.

Если вы сделаете это, вы можете иметь следующее, чтобы компенсировать производительность

shouldComponentUpdate: function(nextProps, nextState){ 
    return this.state.abc !== nextState.abc; 
    // and compare any props that might cause an update 
} 
+0

Итак, я представляю, что было бы намного проще просто сохранить состояние в чем-то помимо 'this.state' и вызвать' render() 'в любое время, когда вы что-то измените внутри него; что считается полным нет-нет среди опытных разработчиков React? – Andy

+0

визуализация - это чистая функция, она на самом деле не делает ничего. Это вызвано реакцией при обновлении, а обновления вызваны вызовами setState. Лучшие практики говорят, что ваш рендер должен производить один и тот же вывод для тех же реквизитов и состояний. Это также упрощает оптимизацию, например, shouldComponentUpdate. – FakeRainBrigand

+0

Ничего себе, я так долго отсутствовал от SO? На самом деле я фактически использовал некоторые базовые реактивные инструменты для вызова 'forceUpdate()' всякий раз, когда изменялись поля модели Backbone. Из-за этого я могу просто переопределить 'shouldComponentUpdate', чтобы вернуть false. 'render' все еще производит одинаковый вывод для тех же« реквизитов »и« состояния »(т. е. моделей Backbone, я ничего не храню в' this.state'). – Andy

74

1) this.setState ({abc.xyz: 'новое значение'}); синтаксис не допускается. Вы должны передать весь объект.

this.setState({abc: {xyz: 'new value'}}); 

Если у вас есть другие переменные в аЬс

var abc = this.state.abc; 
abc.xyz = 'new value'; 
this.setState({abc: abc}); 

2) Вы можете иметь обычные переменные, если они не опираются на this.props и this.state.

+10

Если вы хотите сохранить другие свойства в объекте, полезен метод, например, подчеркивание [extend] (http://underscorejs.org/#extend): 'this.setState ({abc: _.extend (this.state.abc, {xyz : «новое значение»})}); ' – smhg

+0

@s mhg, вы должны опубликовать это как ответ. Я думаю, что это самое чистое решение. Дайте мне знать, когда вы это сделаете, я могу его продвинуть :) –

+0

@ Zoltán это на самом деле то же самое, что и ответ аддона дополнения (в настоящее время выше). Реагент 'React.addons.update' помощник является заменой для' подчеркивания 'подчеркивания. – smhg

11

this.setState({abc: {xyz: 'new value'}}); не будет работать, так как state.abc будет полностью переписан, не сливались.

Это работает для меня:

this.setState((previousState) => { 
    previousState.abc.xyz = 'blurg'; 
    return previousState; 
}); 

Если я читаю документы неправильно, Facebook рекомендует данный формат. https://facebook.github.io/react/docs/component-api.html

Кроме того, я думаю, самый прямой путь без мутирует состояние является непосредственно скопировать с помощью оператора распространения/отдыха ES6:

const newState = { ...this.state.abc }; // deconstruct state.abc into a new object-- effectively making a copy 
newState.xyz = 'blurg'; 
this.setState(newState); 
+0

Я проверил ваш первый способ, используя 'componentDidUpdate()', и он правильно провел предыдущее состояние при выполнении 'this.setState ({[abc.xyz]: 'blurg'})' дал неверное предыдущее состояние, поэтому я предполагаю, что это хорошо , –

+0

не уверен, что вы имеете в виду «неправильное предыдущее состояние» ... – jasonseminara

+0

Предыдущее государство не было фактически предыдущим. Это было currentState, что неверно. –

0

Он работал для меня.

_onPress =() => { 
    this.state.abc.xyz = "new value"; 
    this.setState({}); 
} 
+3

Это неправильная практика. Государство никогда не должно быть мутировано напрямую. Это написано в их документах –

3

Несмотря на то, что может быть сделано с помощью immutability-helper или подобного я не wan't добавить внешних зависимостей в мой код, если я действительно не придется. Когда мне это нужно, я использую Object.assign.Код:

this.setState({ abc : Object.assign({}, this.state.abc , {xyz: 'new value'})}) 

Может использоваться на HTML Атрибуты событий, а также, например:

onChange={e => this.setState({ abc : Object.assign({}, this.state.abc, {xyz : 'new value'})})} 
9

Вы можете распространить предыдущие значения в объекте, чтобы избежать чрезмерной написать

this.setState({ 
    abc: { 
      ...this.state.abc, 
      xyz: 'new value' 
      } 
});