2017-08-29 73 views
4

我的店看起来是这样的,在React/Redux还原器中,我如何以不可变的方式更新嵌套数组中的字符串?

{ 
    name: "john", 
    foo: {}, 
    arr: [ 
     { 
     id:101, 
     desc:'comment' 
     }, 
     { 
     id:101, 
     desc:'comment2' 
     } 
    ] 
} 

我textarea的看起来像这样

<textarea 
    id={arr.id} //"101" 
    name={`tesc:`} 
    value={this.props.store.desc} 
    onChange={this.props.onChng} 
/> 

我的动作是

export const onChng = (desc) => ({ 
    type: Constants.SET_DESC, 
    payload: { 
    desc 
    } 
}); 

我减速

case Constants.SET_DESC: 
    return update(state, { 
    store: { 
     streams: { 
     desc: { $set: action.payload.desc } 
     } 
    } 
}); 

它的工作原理Ø NLY如果ARRY是一个对象,我不得不做出更改流到一个数组,我很困惑我怎么可以更新到一个数组,还如何得到商店正确的价值。

+1

你怎么要更新的阵列?修改数组中的元素或添加一个新元素,删除一个等等? – Li357

+0

我想添加一个新的元素?在{{id:101,here}}旁边# –

+1

你如何确定ID? – Li357

回答

0

要更新一个数组,我会用immutability helper和做这样的事情 - 给你的减速器

let store = {"state" : { 
"data": [{ 
    "subset": [{ 
     "id": 1 
    }, { 
     "id": 2 
    }] 
}, { 
    "subset": [{ 
     "id": 10 
    }, { 
     "id": 11 
    }, { 
     "id": 12 
    }] 
}] 
}} 

case Constants.SET_DESC: 
    return update(store, { 
    "state" : { 
    "data": { 
     [action.indexToUpdate]: { 
     "subset": { 
      $set: action.payload.desc 
     } 
     } 
    } 
} 
    }) 
    }); 
+0

这就是我想要实现它..我已经将immutable-helper下载到我的项目中,但是它不工作 - 没有找到indexToUpdate –

+0

奋力感谢.. –

2

以下来自redux文档的示例可能会帮助您在用例中如何更新数组中的项目。欲了解更多关于这一点,你可以阅读这里http://redux.js.org/docs/recipes/StructuringReducers.html

状态的结构是这样的

{ 
    visibilityFilter: 'SHOW_ALL', 
    todos: [ 
    { 
     text: 'Consider using Redux', 
     completed: true, 
    }, 
    { 
     text: 'Keep all state in a single tree', 
     completed: false 
    } 
    ] 
} 

和减速器代码就像下面

function updateObject(oldObject, newValues) { 
    // Encapsulate the idea of passing a new object as the first parameter 
    // to Object.assign to ensure we correctly copy data instead of mutating 
    return Object.assign({}, oldObject, newValues); 
} 

function updateItemInArray(array, itemId, updateItemCallback) { 
    const updatedItems = array.map(item => { 
     if(item.id !== itemId) { 
      // Since we only want to update one item, preserve all others as they are now 
      return item; 
     } 

     // Use the provided callback to create an updated item 
     const updatedItem = updateItemCallback(item); 
     return updatedItem; 
    }); 

    return updatedItems; 
} 

function appReducer(state = initialState, action) { 
    switch(action.type) { 
     case 'EDIT_TODO' : { 
      const newTodos = updateItemInArray(state.todos, action.id, todo => { 
       return updateObject(todo, {text : action.text}); 
      }); 

      return updateObject(state, {todos : newTodos}); 
     } 
     default : return state; 
    } 
} 
+0

我希望做的结构我也问过。意思你如何访问一个商店阵列 –

+0

'state.todos'是数组 –

+0

不幸的是我不明白..但是谢谢你尝试 –

1

我如果必须更新商店内数组中的元素,则必须复制数组并复制匹配元素以应用更改。

因此,在第一步中,您的操作应该包含已克隆(和已更改)的对象或对象的ID以及要更改的属性。

这里是一个粗略的例子:

export class MyActions { 
    static readonly UPDATE_ITEM = 'My.Action.UPDATE_ITEM'; 

    static updateItem(id: string, changedValues: any) { 
     return { type: MyActions.UPDATE_ITEM, payload: { id, changedValues } }; 
    } 
} 

export const myReducer: Reducer<IAppState> = (state: IAppState = initialState, action: AnyAction): IAppState => { 
    switch (action.type) { 
     case MyActions.UPDATE_ITEM: 
      return { ...state, items: merge(state.items, action.payload) }; 

     default: 
      return state; 
    } 
} 

const merge = (array, change) => { 
    // check if an item with the id already exists 
    const index = array.findIndex(item => item.id === change.id); 
    // copy the source array 
    array = [...array]; 

    if(index >= 0) { 
     // clone and change the existing item 
     const existingItem = array[index]; 
     array[index] = { ...existingItem, ...change.changedValues }; 
    } else { 
     // add a new item to the array 
     array.push = { id: change.id, ...change.changedValues }; 
    } 

    return array; 
} 
+0

将在'array'看起来像你的榜样吗? –

+0

'数组'包含你的对象。例如。 '{id:string,desc:string}'。如果你的对象还包含一些其他对象的数组,你必须将上述逻辑嵌套更多一层,而'changedValues'对象也包含一个id属性。如果这是你的情况,你不知道如何做到这一点,给我一个提示,我会更新我的答案。 – Oliver

相关问题