简体   繁体   English

当数组尚不存在时,如何在 Redux 中的 reducer 中向数组添加元素?

[英]How do I add an element to array in reducer in Redux when the array does not yet exist?

I have a code sandbox to demo an issue I am having with Redux and React.我有一个代码沙箱来演示我在 Redux 和 React 中遇到的问题。

https://codesandbox.io/s/reactredux-3edy8 https://codesandbox.io/s/reactredux-3edy8

Basically this reducer does not work:基本上这个减速器不起作用:

const initialState = {
  byId: {}
};

function addReducer(state = initialState, action) {
  switch (action.type) {
    case "RECEIVE_DATA":
      return {
        ...state,
        byId: {
          ...state.byId,
          [action.payload.id]: [
            ...state.byId[action.payload.id],
            action.payload.data
          ]
        }
      };
    default:
      return state;
  }
}

export default addReducer;

here is the action:这是行动:

import { RECEIVE_DATA } from "./actionTypes";

export function action() {
  return {
    type: RECEIVE_DATA,
    payload: {
      id: Math.floor(Math.random() * 2),
      data: Math.floor(Math.random() * 10000)
    }
  };
}

In my own app it throws an error like state.byId[action.payload.id] is not iterable which is true.在我自己的应用程序中,它会抛出一个错误,例如state.byId[action.payload.id] is not iterable 这是真的。 But how do I push values to an array that does not yet exist because I do not know the id ?但是如何将值推送到一个尚不存在的数组,因为我不知道id

I thought the issue might be solved by changing the initialState or perhaps there is a function I am not aware of that allows me to either create an array or push to it.我认为这个问题可以通过更改initialState来解决,或者可能有一个我不知道的函数允许我创建一个arraypush送到它。

Check if the array exists first.首先检查数组是否存在。 If it does, add a new element.如果是,请添加一个新元素。 If not, create a new array with one element (the new data from the action)如果不是,则创建一个包含一个元素的新数组(来自动作的新数据)

const initialState = {
  byId: {}
};

function addReducer(state = initialState, action) {
  switch (action.type) {
    case "RECEIVE_DATA":
      return {
        ...state,
        byId: {
          ...state.byId,
          [action.payload.id]: (
              state.byId[action.payload.id] ? [
              ...state.byId[action.payload.id],
              action.payload.data
            ] : [action.payload.data])
        }
      };
    default:
      return state;
  }
}

export default addReducer;

You can read more about ternary statements here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator您可以在此处阅读有关三元语句的更多信息: https : //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator

I am not sure but I think you need something like this我不确定,但我认为你需要这样的东西

 function addReducer(state = initialState, action) {
      switch (action.type) {
        case "RECEIVE_DATA":
          return {
            ...state,
            byId: {
              ...state.byId,
              [action.payload.id]: 
                [action.payload.data]

            }
          };
        default:
          return state;
      }
    }

The answer to this problem lies in flattening the state.这个问题的答案在于扁平化状态。 I am sure there are other ways to fix this problem, but I found this the cleanest.我确信还有其他方法可以解决这个问题,但我发现这是最干净的。

Typically the byId property of state is created through flattening state per the guidelines in the docs通常,状态的byId属性是根据文档中的指南通过展平状态创建

I take it one step further, making the byId property an Array instead of an Object.我更进一步,使byId属性成为一个数组而不是一个对象。 I move the id into the objects of the array like in this new sandbox: https://codesandbox.io/s/reactredux-zj1n4我将id移动到数组的对象中,就像在这个新沙箱中一样: https : //codesandbox.io/s/reactredux-zj1n4

I just have to remember the byId is now an array when I map the state to my components.我只需要记住当我将状态映射到我的组件时byId现在是一个数组。

No functionality is lost and my byId field can now support multiple different ids if needed (eg if I had many to many relationships on the objects)没有任何功能丢失,如果需要,我的byId字段现在可以支持多个不同的 id(例如,如果我在对象上有多对多关系)

Here is the code:这是代码:

in reducer在减速机

case "RECEIVE_DATA":
      return {
        ...state,
        byId: [...state.byId, action.payload.data]
      };

new action:新动作:

export function action() {
  return {
    type: RECEIVE_DATA,
    payload: {
      data: {
        id: Math.floor(Math.random() * 2),
        value: Math.floor(Math.random() * 10000)
      }
    }
  };
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM