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;
    }    
}