[英]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
来解决,或者可能有一个我不知道的函数允许我创建一个array
或push
送到它。
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.