使用不可变的js,是否有更好的方法来更新不可变对象中此数组的值?

时间:2016-12-03 16:25:12

标签: javascript reactjs redux immutability immutable.js

所以在我的react redux项目中,我正在更新我的状态数组:

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

所以只是简单地分解它我正在使用一个普通的js状态对象将它变为不可变,然后使用一个新的不可变的数组副本设置所选的值并推入一个新的值。

在我看来这是实现这一目标的唯一方法,同时确保我将状态视为不可变值。我以为我能做到这一点:

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)我在那里创建了两次不可变对象

2 个答案:

答案 0 :(得分:1)

使用List结构,文档: https://facebook.github.io/immutable-js/docs/#/List

它有一个push操作。 因此,如果您this.state包含名为rayythis.state.rayy)的数组,假设您可以说:

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

这不会改变原作,只会返回一个新副本并将其分配给rayy

请记住,在与Redux一起使用React时,有两个不同的state。有一个Redux state商店超越任何特定组件,应该可以从任何地方访问,然后有个别组件的state。我使用Redutable和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,这不是任何问题,因为这些变量是组件专用的,通常只涉及瞬态UI的东西,所以典型的使用Immutables的原因并不引人注目。

另一方面,在我的Reducer(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中可以使用最后一个(简洁)版本,因为它具有隐式返回。

答案 1 :(得分: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)