Redux reducer,检查状态数组中是否存在值并更新状态
Redux reducer, check if value exists in state array and update state
所以我有一个数组 chosenIds[]
,它基本上包含 ids (numbers)
的列表。但是我无法访问我的减速器中的状态来检查 ID I parsed to my action
是否在数组中。
const initialState = {
'shouldReload': false,
'chosenIds': [],
};
export default function filter(state = initialState, action) {
switch (action.type) {
case ADD_TYPE:
console.log(state.chosenIds, "Returns undefined???!!!");
// Check if NUMBER parsed is in state
let i = state.chosenIds.indexOf(action.chosenId);
//If in state then remove it
if(i) {
state.chosenIds.splice(i, 1);
return {
...state.chosenIds,
...state.chosenIds
}
}
// If number not in state then add it
else {
state.chosenIds.push(action.chosenId)
return { ...state.chosenIds, ...state.chosenIds }
}
我不确定发生了什么...但是当我登录 state.chosenIds
时,它 return 未定义?它甚至没有 return 初始空数组 []
.
基本上这个函数要做的是检查 action.chosenId
是否在 state.chosenIds
中,如果是,则删除 action.chosenId
值,如果不是, 然后将 action.chosenId
添加到 state.
我在这里看到了几个不同的问题。
首先,您在已处于状态的阵列上使用 splice()
和 push()
。这是直接突变,它破坏了 Redux。您需要复制数组,然后修改该副本。
其次,对象展开使用看起来不对。您正在使用它,就好像 "chosenIds" 是一个对象,但它是一个数组。此外,您正在复制价差。这导致返回的状态不再具有名为 "chosenIds".
的字段
第三,Array.indexOf() returns -1 如果没有找到,其实算作"truthy",因为它不是0。所以,当前的if/else不会'不如你想的那样。
我会重写你的 reducer 如下所示:
export default function reducer(state = initialState, action) {
switch(action.type) {
case ADD_TYPE:
let idAlreadyExists = state.chosenIds.indexOf(action.chosenId) > -1;
// make a copy of the existing array
let chosenIds = state.chosenIds.slice();
if(idAlreadyExists) {
chosenIds = chosenIds.filter(id => id != action.chosenId);
}
else {
// modify the COPY, not the original
chosenIds.push(action.chosenId);
}
return {
// "spread" the original state object
...state,
// but replace the "chosenIds" field
chosenIds
};
default:
return state;
}
}
另一种具有独立功能的方法:
export default function reducer(state = initialState, action) {
switch(action.type) {
case ADD_TYPE:
function upsert(array, item) {
// (1)
// make a copy of the existing array
let comments = array.slice();
const i = comments.findIndex(_item => _item._id === item._id);
if (i > -1) {
comments[i] = item;
return comments;
}
// (2)
else {
// make a copy of the existing array
let comments = array.slice();
comments.push(item);
return comments;
}
}
return {
...state,
comments: upsert(state.comments, action.payload),
};
default:
return state;
}
}
所以我有一个数组 chosenIds[]
,它基本上包含 ids (numbers)
的列表。但是我无法访问我的减速器中的状态来检查 ID I parsed to my action
是否在数组中。
const initialState = {
'shouldReload': false,
'chosenIds': [],
};
export default function filter(state = initialState, action) {
switch (action.type) {
case ADD_TYPE:
console.log(state.chosenIds, "Returns undefined???!!!");
// Check if NUMBER parsed is in state
let i = state.chosenIds.indexOf(action.chosenId);
//If in state then remove it
if(i) {
state.chosenIds.splice(i, 1);
return {
...state.chosenIds,
...state.chosenIds
}
}
// If number not in state then add it
else {
state.chosenIds.push(action.chosenId)
return { ...state.chosenIds, ...state.chosenIds }
}
我不确定发生了什么...但是当我登录 state.chosenIds
时,它 return 未定义?它甚至没有 return 初始空数组 []
.
基本上这个函数要做的是检查 action.chosenId
是否在 state.chosenIds
中,如果是,则删除 action.chosenId
值,如果不是, 然后将 action.chosenId
添加到 state.
我在这里看到了几个不同的问题。
首先,您在已处于状态的阵列上使用 splice()
和 push()
。这是直接突变,它破坏了 Redux。您需要复制数组,然后修改该副本。
其次,对象展开使用看起来不对。您正在使用它,就好像 "chosenIds" 是一个对象,但它是一个数组。此外,您正在复制价差。这导致返回的状态不再具有名为 "chosenIds".
的字段第三,Array.indexOf() returns -1 如果没有找到,其实算作"truthy",因为它不是0。所以,当前的if/else不会'不如你想的那样。
我会重写你的 reducer 如下所示:
export default function reducer(state = initialState, action) {
switch(action.type) {
case ADD_TYPE:
let idAlreadyExists = state.chosenIds.indexOf(action.chosenId) > -1;
// make a copy of the existing array
let chosenIds = state.chosenIds.slice();
if(idAlreadyExists) {
chosenIds = chosenIds.filter(id => id != action.chosenId);
}
else {
// modify the COPY, not the original
chosenIds.push(action.chosenId);
}
return {
// "spread" the original state object
...state,
// but replace the "chosenIds" field
chosenIds
};
default:
return state;
}
}
另一种具有独立功能的方法:
export default function reducer(state = initialState, action) {
switch(action.type) {
case ADD_TYPE:
function upsert(array, item) {
// (1)
// make a copy of the existing array
let comments = array.slice();
const i = comments.findIndex(_item => _item._id === item._id);
if (i > -1) {
comments[i] = item;
return comments;
}
// (2)
else {
// make a copy of the existing array
let comments = array.slice();
comments.push(item);
return comments;
}
}
return {
...state,
comments: upsert(state.comments, action.payload),
};
default:
return state;
}
}