如何在redux中更新数组内部的单个值

时间:2018-02-27 15:59:12

标签: reactjs redux state

我正在使用reactredux创建一个todolist,当我更新redux状态数组时,它不会重新渲染,我的状态实际上是一个包含对象的数组,就像这样:

[{index:1,value:'item1',done:false}, {index:2,value:'item2',done:false}]

我想要做的是点击我想要将完成的值切换为' true', 但不知何故,我无法做到这一点。

这就是我在减速机中所做的事情:

list.map((item)=>{
     if(item.index===index){
         item.done=!item.done;
         return [...state,list]
     }

但是,即使单击切换按钮完成后,它也不会重新渲染。

似乎我不知何故正在改变国家。 请告诉我我哪里出错了,我该怎么做。

你能举出类似的例子吗?我可以正确更新简单数组的状态,但是对于包含对象的数组来说,这让我很困惑。 所以,你能举例说明吗?

这里是完整的reducer代码:

export default function todoApp(state=[],action){
    switch(action.type){
        case 'ADD_TODO':
            return [...state,action.item];
        case 'TOGGLE_TODOS':
            const index = action.index;
            const list = state;

            list.map((item)=>{
            if(item.index===index){
                item.done=!item.done;

            }
            return [...state,list];
            });
        default:
          return state;    
    } 
}

3 个答案:

答案 0 :(得分:4)

  

似乎我不知何故正在改变国家。

纠正你正在改变状态,因为在js中,变量总是得到对象/数组的引用。在您的情况下,item将包含数组中每个对象的引用,并且您将直接改变item.done的值。

另一个问题是你没有正确返回最终对象,你也需要为每个地图迭代返回值,否则默认它会返回undefined

像这样写:

case "TOGGLE_TODOS": 
    return list.map((item) => (
        item.index===index? {...item, done: !item.done}: item
    ))

或者:

case 'TOGGLE_TODOS':
    const index = action.index;
    const newState = [ ...state ];
    newState[index] = { ...state[index], done: !newState[index].done };
    return newState;

完整代码:

export default function todoApp(state=[], action){
    switch(action.type){
        case 'ADD_TODO':
            return [...state, action.item];
        case 'TOGGLE_TODOS':
            const index = action.index;
            return state.map((item) => (
                item.index===index? {...item, done: !item.done}: item
            ))
        default:
            return state;    
    }
}

检查此代码段:



let list = [
    {done:true, index:0},
    {done:false, index:1},
    {done: true, index:2}
  ]

let index = 1;

let newList = list.map(item => (
    item.index===index? {...item, done: !item.done}: item
))

console.log('newList = ', newList);




答案 1 :(得分:1)

查看Array.prototype.Map的文档。

回调函数应该返回新数组的元素。试试这个:

return list.map(item => {
  if (item.index === index) {
    return {
      done: !item.done
      ...item,
    }

  return item;
});

答案 2 :(得分:0)

虽然已经存在两个正确的答案,但我也希望将lodash/fp放在这里,这样会更加密集和可读,也不会发生变异

import { set } from 'lodash/fp'

return list.map(item => {
    if (item.index === index) {
        return set('done', !item.done, item)
    }
    return item
}