使用Immutable js,有没有更好的方法来更新不可变对象中这个数组的值?

Using Immutable js, is there a better way to update the value of this array in an immutable object?

所以在我的 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) 我在其中两次创建不可变对象

使用 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)})

这不会改变原件,它只会 return 一个新副本并将其分配给 rayy

请记住,在将 React 与 Redux 一起使用时,有两个不同的 state。 Redux state store 超越任何特定组件,应该可以从任何地方访问,然后是特定于各个组件的 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,这不是任何类型的问题,因为这些变量是组件私有的,并且通常只与瞬态相关 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 中是可能的,因为它隐含了 return。

如果您尝试使用 immutable.js,您应该在整个应用程序中使用它,因为调用 fromJS() 和 toJS() 不利于性能并且需要繁琐的语法,如您的示例所示。

如果你想将你的状态保持为纯 JS 对象,你应该使用我创建的 Object.assign(), Immutability Helpers or other libraries such as 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)