【问题标题】:Update array object in React Redux reducer在 React Redux reducer 中更新数组对象
【发布时间】:2017-10-17 12:57:37
【问题描述】:

这应该很简单,但我没有找到我想要的简单答案。我有一个减速器:

const posts = (state = null, action) => {
  switch(action.type){
    case "PUBLISH_POST":
        return state;
    case "UNPUBLISH_POST":
        return state;
    default:
        return postList;
  }
}

我有一个带有IDstatus 的帖子列表。我正在发送我的帖子 ID,但无法弄清楚将已单击项目的 status 从 0 更新为 1 的逻辑。我找到了很多半解决方案,但它们都显得冗长而丑陋 - 在这种情况下,实现它的最短/最佳方法是什么?

示例数据:

{
    id:1,
    user:"Bob Smith",
    content:"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque vulputate mauris vitae diam euismod convallis. Donec dui est, suscipit at dui vitae, sagittis efficitur turpis. ",
    status:1 
}

【问题讨论】:

  • 您的状态如何?是帖子数组吗?
  • @mersocarlin 是的,上面的例子
  • 什么是动作负载?

标签: reactjs redux


【解决方案1】:

假设您的 action 类似于:

{
  type: 'UNPUBLISH_POST',
  payload: {
    id: 1,
    user: 'Bob Smith',
    content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque vulputate mauris vitae diam euismod convallis. Donec dui est, suscipit at dui vitae, sagittis efficitur turpis. ',
    status: 1
  }
}

只需使用spread operator 即可:

const posts = (state = null, action) => {
  switch(action.type){
    case "PUBLISH_POST":
    case "UNPUBLISH_POST":
        const index = this.state.findIndex(post => post.id === action.payload.id)

        return [
           ...state.slice(0, index), // everything before current post
           {
              ...state[index],
              status: action.type === 'PUBLISH_POST' ? 1 : 0,
           },
           ...state.slice(index + 1), // everything after current post
        ]
    default:
        return postList;
  }
}

【讨论】:

  • 谢谢。我不得不删除“这个”。从国家。我意识到我不能只做一个切换,而不是两个条件。
  • @MattSaunders 不客气。我刚刚注意到您的state 默认为null。也许将它初始化为一个空数组,这样你以后就不会有问题了:)
  • 您也可以考虑使用immutability-helper 模块以及here 描述的模式。
  • 感谢 slice 方法,对 redux 非常有用;)
  • 谢谢你,真的很有帮助
【解决方案2】:

一个更通用的解决方案,特别是如果 state 包含除 posts 数组之外的其他数据:

const posts = (state = null, action) => {
  const post = state.posts.find(p => p.id === action.payload.id);
  switch(action.type) {
    case "PUBLISH_POST":
      return { ...state, posts: [ ...state.posts.filter(p => p !== post), { ...post, status: 1 } ] };
    case "UNPUBLISH_POST":
      return { ...state, posts: [ ...state.posts.filter(p => p !== post), { ...post, status: 0 } ] };
    default:
      return state;
  }
}

【讨论】:

  • 我想你想返回filter(p => p !== post) 并更新帖子?
  • @KerSplosh 你完全正确,谢谢。根据您的评论更新了答案。
  • 这不会改变帖子数组的顺序吗?
  • @slavlazar 是的。如果您需要保留订单,请使用 mersocarlin 的解决方案,使用 slice
【解决方案3】:

假设您有一个帖子数组,您可以搜索要修改的帖子的 ID,然后对其进行更新。

你的初始状态:

const initial = {
   posts: [],
}

你的减速器:

case MODIFY_POST:
        return {
            ...state, //Returns the current state
            posts: state.posts.map(post=> post.id === action.id ? // Loop through the array to find the post you want to modify
                { ...post, status: action.status} : post // Copy the post state and then modify it. Else return the same object.
            )
        }

现在,在您的操作中,您可以使用两个操作来切换状态:

export const enablePost= (post_id) => {
return {
    type: MODIFY_POST,
    id: post_id,
    status: 1
    }
}
export const disablePost= (post_id) => {
return {
    type: MODIFY_POST,
    id: post_id,
    status: 0
    }
}

【讨论】:

    【解决方案4】:

    您可以在您的状态上使用扩展运算符,它会自动按照您想要的方式更新它。

    示例:

        import { GET_ALL_PENDING_DATAOPS, CHANGE_DATAOPS_ASSIGNED_TO } from "../Actions/types";
    const initialState = {
      requests: null
    };
    export default function(state = initialState, action) {
      const { type, payload } = action;
    
      switch (type) {
        case GET_ALL_PENDING_DATAOPS:
          return {
            ...state,
            requests: payload
          };
          case CHANGE_DATAOPS_ASSIGNED_TO:          
            return {
              ...state,      
              requests:payload         
            }
        default:
          return state;
      }
    }
    

    我的 CHANGE_DATAOPS_ASSIGNED_TO 操作映射了以前的状态,在我的 axios 调用中,我正在从请求数组中更新单个请求对象,因为它返回单个对象,并且我没有明确地将其作为状态返回,我我正在使用传播,它只更新那个对象,其余的不理会。

    【讨论】:

    • 感谢您添加答案。您能否将您的代码包含在答案中而不是图像中?在 Stack Overflow 上发布代码截图是不好的做法。
    猜你喜欢
    • 2018-06-03
    • 1970-01-01
    • 1970-01-01
    • 2018-01-11
    • 2019-05-07
    • 1970-01-01
    • 1970-01-01
    • 2022-01-25
    • 2016-08-16
    相关资源
    最近更新 更多