在React Redux reducer

时间:2017-10-17 12:57:37

标签: reactjs redux

这应该很简单,但我找不到我想要的简单答案。我有减速机:

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 
}

4 个答案:

答案 0 :(得分:10)

假设您的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;
  }
}

答案 1 :(得分:4)

更通用的解决方案,特别是如果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;
  }
}

答案 2 :(得分:2)

假设您有一个帖子数组,您可以搜索您要修改的帖子的 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
    }
}

答案 3 :(得分:0)

您只需在状态上使用传播运算符,它将自动以您想要的方式对其进行更新。

示例:

    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调用中,我正在从请求数组中更新单个请求对象,因为它返回的是单个对象,并且我没有明确地将其返回为状态,我在使用传播时,它只会更新该对象,而不会剩下其余的。