2016-12-03 3 views
1

поэтому в моей реакцию Redux проекта я обновляя массив в моем государстве, как это:Использование неизменяемых js, есть ли лучший способ обновить значение этого массива в неизменяемом объекте?

this.setState(fromJS(this.state).set(e.target.id, fromJS(this.state).get(e.target.id).push(e.target.value)).toJS()); 

Так просто кратко разбить его я беру равнину расслоения плотного состояния объект поворачивая его неизменным затем установить выбранное значение с новая неизменяемая копия массива с новым значением, вдавленным.

Это казалось мне единственным способом сделать это, убедившись, что я рассматриваю состояние как неизменяемое значение. Я думал, что я могу это сделать:

this.setState(fromJS(this.state).set(e.target.id, this.state[e.target.id].push(e.target.value)).toJS()); 

Выше я предполагаю, мутирует исходное состояние, поэтому я полагал, что я не должен использовать его. Является ли метод, который я выбираю первым, самый эффективный способ убедиться, что все неизменное? Я чувствую, что собираюсь и снова создаю новый объект, чтобы получить новое значение массива, кажется слишком сложным, поэтому мне интересно, есть ли лучший способ сделать это.

Опять мой основной акцент делается на этой линии: .set(e.target.id, fromJS(this.state).get(e.target.id).push(e.target.value) где я создаю неизменяемый объект дважды

+0

Вы не хватает точки неизменных данных? Вы в настоящее время просто используете Immutable.js, чтобы сделать _very_ фантазии глубокого клонирования вашего объекта. – Prinzhorn

+0

Думаю? Можете ли вы объяснить, что вы имеете в виду? Разве это не то, что я делаю выше, убедившись, что я устанавливаю свое состояние на новый объект, а затем мутирую оригинал? По-настоящему любопытно, потому что честно это все ново для меня, и я бы сказал последним, что знаю, что, черт возьми, я делаю. –

+0

Являются ли значения в вашем состоянии равными объектами/массивами или являются ли они неизменными.Map/List и т. Д.? Если они есть, то вам не нужно быть уверенным, что вы не мутируете оригинал, потому что вы ** не можете **. – Prinzhorn

ответ

1

Использование в List структура, документы здесь: https://facebook.github.io/immutable-js/docs/#/List

Он имеет push операцию. Так что если у вас есть this.state, содержащий массив с именем rayy (this.state.rayy), гипотетически, можно сказать:

this.setState({ rayy: this.state.rayy.push(e.target.value)}) 

Это не будет мутировать оригинал он просто возвращает новую копию и назначить его rayy.

Помните, что существуют два отличных state s при работе с React вместе с Redux. Существует магазин Redux state, который выходит за любой конкретный компонент и должен быть доступен из любого места, а затем есть state, специфичный для отдельных компонентов. Я использую Immutable с Redux, но в компонентах state не является неизменным. Итак:

[...][coffeescript here] 
# components' state (not immutable) 
getInitialState: -> 
    some_ui_thing: 42 
    another_ui_thing: 43 

# for Redux's connect: (Redux's state is immutable, transition it to JS for props & render stuff 
mapStateToProps: (state) -> 
    state.toJS() 

Теперь в моих компонентах, когда я звоню @setState это просто изменяемые JS, которая не является каким-либо видом вопроса, потому что эти вары являются частными по отношению к компоненту, и, как правило, относятся только к преходящей вещи пользовательского интерфейса, так типичные причины использования непременного Arent.

С другой стороны, в моих переходниками (Redux), я мог бы иметь функцию:

do_something = (state, action) -> 
    state = state.setIn ['rayy'], state.rayy.push(action.payload.whatever) 
    state 

я мог бы сделать его более четко:

do_something = (state, action) -> 
    some_list = state.getIn ['rayy'] 
    some_list = some_list.push action.payload.whatever 
    state = state.setIn ['rayy'], some_list 
    return state 

Или более лаконичной:

do_something = (state, action) -> 
    state.setIn ['rayy'], state.rayy.push(action.payload.whatever) 

Эта последняя (краткая) версия возможна в coffeescript, потому что она имеет неявный возврат.

0

Если вы пытаетесь использовать immutable.js, вы должны использовать его во всем приложении, потому что вызов fromJS() и toJS() является плохим для производительности и требует утомительного синтаксиса, как в вашем примере.

Если вы хотите сохранить свое состояние в виде простых объектов JS, вы должны использовать Object.assign(), Immutability Helpers или другие библиотеки, такие как immutable-assign, созданный мной. Пример использования:

var newState = iassign(this.state, 
 
    function(state, context) { return state[context.id]; }, 
 
    function(prop) { prop.push(e.target.value); return prop; }, 
 
    { id: e.target.id } 
 
) 
 
this.setState(newState); 
 

 
// The first parameter is a function that return the property you need 
 
// to modify in your state. This function must be **pure function**, 
 
// therefore "id" need to be passed in via the context parameter. 
 
// 
 
// The second parameter is a function that modify selected property of your 
 
// state, it doesn't need to be pure, therefore you can access 
 
// "e.target.value" directly 
 
// 
 
// The third parameter is the context used in the first function (pure function)