React Redux,如何正确处理数组中更改的对象?

时间:2016-01-18 22:23:01

标签: arrays reactjs redux

我有一个React Redux应用程序,它从我的服务器获取数据并显示该数据。

我在父容器中显示的数据类似于:

render(){
    var dataList = this.props.data.map( (data)=> <CustomComponent key={data.id}> data.name </CustomComponent>)

    return (
        <div>
           {dataList}
        </div>
    )
}

当我与我的应用程序交互时,有时候,我需要更新特定的CustomComponent。

由于每个CustomComponent都有一个id,我将其发送到我的服务器,其中包含一些用户选择的数据。 (即它是一种形式)

服务器使用该ID的更新对象进行响应。

在我的redux模块中,我遍历当前的data状态,找到id为

的对象
export function receiveNewData(id){
    return (dispatch, getState) => {
        const currentData = getState().data
        for (var i=0; i < currentData.length; i++){
            if (currentData[i] === id) {
                const updatedDataObject = Object.assign({},currentData[i], {newParam:"blahBlah"})
                allUpdatedData = [
                    ...currentData.slice(0,i),
                    updatedDataObject,
                    ...currentData.slice(i+1)
                ]
                dispatch(updateData(allUpdatedData))
                break
            }
        }
    }
}


const updateData = createAction("UPDATE_DATA")

createAction来自redux-actions,它基本上创建了{type, payload}的对象。 (它标准化动作创作者)

无论如何,从这个例子中你可以看到每次我有一个变化时我会不断遍历整个数组以确定哪个对象正在发生变化。

考虑到我已经拥有该对象的id,这对我来说似乎效率低下。

我想知道是否有更好的方法来处理React / Redux?有什么建议?

2 个答案:

答案 0 :(得分:3)

你的行动创造者做得太多了。它承担了属于减速机的工作。您的所有动作创建者都需要做的是宣布要更改的内容,而不是如何更改它。 e.g。

export function updateData(id, data) {
    return {
        type: 'UPDATE_DATA',
        id: id,
        data: data
    };
}

现在将所有逻辑移到reducer中。 e.g。

case 'UPDATE_DATA':
    const index = state.items.findIndex((item) => item.id === action.id);
    return Object.assign({}, state, {
        items: [
            ...state.items.slice(0, index),
            Object.assign({}, state.items[index], action.data),
            ...state.items.slice(index + 1)
        ]
    });

如果您担心Array#findIndex的O(n)调用,请考虑使用normalizr(或类似内容)重新编制数据索引。但是,只有在遇到性能问题时才能执行此操作;对于小数据集,它不是必需的。

答案 1 :(得分:1)

为什么不使用id索引的对象?然后,您只需使用它来访问对象的属性。

 const data = { 1: { id: 1, name: 'one' }, 2: { id: 2, name: 'two' } }

然后你的渲染将如下所示:

render () {

  return (
    <div>
     {Object.keys(this.props.data).forEach(key => {
       const data = this.props.data[key]
       return <CustomComponent key={data.id}>{data.name}</CustomComponent>
     })}
    </div>
  )
}

接收数据操作,我稍后更新了一下:

export function receiveNewData (id) {
  return (dispatch, getState) => {
    const currentData = getState().data

    dispatch(updateData({
      ...currentData,
      [id]: {
        ...currentData[id],
        { newParam: 'blahBlah' }
      }
    }))
  }
}

虽然我同意David的意见,但很多动作逻辑应该转移到你的reducer处理程序。