【问题标题】:How to remove an element from an array in ReactJS Redux state, when a condition is true?当条件为真时,如何从 ReactJS Redux 状态的数组中删除元素?
【发布时间】:2021-06-08 07:11:09
【问题描述】:

基本上我有一个包含项目行的表格。这些行有 4 个包含文本的单元格。您可以从右侧 -> 左侧的行中删除单元格/文本。因此,“1 2 3 4”可以是“1 2 3 -”,例如,如果您从右 -> 左删除单元格/文本。

这是我的 reducer 代码,我还必须删除整个行,因为上面示例中的“1”也被删除了。这只是为了让我不想让一行可见,例如“- - - -”,它可以在那时删除整行。所以这是我的代码:

case DELETE_SITE: {
      return {
        ...state,
        siteRows: state.siteRows.map((s) => {
          if (s.siteLevel2Id && s.siteLevel2Id == action.payload.id) 
            //return {...s, siteLevel2Id: null, siteLevel2Name: null, canDeleteLevel2: null};
            return state.siteRows.slice(0, 1);
          if (s.siteLevel3Id && s.siteLevel3Id == action.payload.id) 
            return {...s, siteLevel3Id: null, siteLevel3Name: null, canDeleteLevel3: null};
          if (s.siteLevel4Id && s.siteLevel4Id == action.payload.id) 
            return {...s, siteLevel4Id: null, siteLevel4Name: null, canDeleteLevel4: null};
          if (s.siteLevel5Id && s.siteLevel5Id == action.payload.id) 
            return {...s, siteLevel5Id: null, siteLevel5Name: null, canDeleteLevel5: null};
          return s;
         }),
      }
    }  

如您所见,只要删除3、2,仍然会填入1,看起来像这样“1 - - -”。现在如果我们也删除“1”,这里命名为“siteLevel2...”,它会显示“- - - -”,但我只想从“state.siteRows”中删除整行。

我现在已经尝试了注释中的行,但它只是将一个“null”值添加到“siteRows”数组中,如下所示:{null, [siteRow1]} 所以它在我的屏幕上崩溃,因为它正在尝试执行“null.id”之类的操作。

我已经尝试在第二行拼接数组中的第一个元素(删除它),但它似乎也不起作用。

谁能帮我解决这个问题?

【问题讨论】:

    标签: reactjs redux rxjs state


    【解决方案1】:

    您可以尝试以下方法:

    const DELETE_SITE = 'DELETE_SITE';
    const testReducer = (state, action) => {
      switch (action.type) {
        case DELETE_SITE: {
          const keys = [
            ['siteLevel2Id', 2],
            ['siteLevel3Id', 3],
            ['siteLevel4Id', 4],
            ['siteLevel5Id', 5],
          ];
          const reset = (num, item) => ({
            ...item,
            [`siteLevel${num}Id`]: null,
            [`siteLevel${num}Name`]: null,
            [`canDeleteLevel${num}`]: null,
          });
          const recurCheck = (id) => (row) => {
            const recur = (index) => {
              const [currentKey, num] = keys[index];
              //nothing to do, no match
              if (index >= keys.length - 1) {
                return row;
              }
              //row siteLevelNId matches id, reset this row
              if (row[currentKey] && row[currentKey] == id) {
                return reset(num, row);
              }
              //recur try the next index
              return recur(index + 1);
            };
            return recur(0);
          };
          return {
            ...state,
            siteRows: state.siteRows
              .map(recurCheck(action.payload?.id))
              //if any of these keys return true
              //  do not remove this row
              .filter((row) => keys.some(([key]) => row[key])),
          };
        }
        default: {
          return state;
        }
      }
    };
    console.log(
      'no rows',
      testReducer(
        { siteRows: [] },
        { type: DELETE_SITE, payload: { id: 1 } }
      ).siteRows
    );
    const createItem = (num) => ({
      [`siteLevel${num}Id`]: num,
      [`siteLevel${num}Name`]: num,
      [`canDeleteLevel${num}`]: num,
    });
    console.log(
      'id 3',
      testReducer(
        { siteRows: [createItem(3)] },
        { type: DELETE_SITE, payload: { id: 3 } }
      ).siteRows
    );
    console.log(
      'id 2',
      testReducer(
        { siteRows: [{ ...createItem(2), siteLevel3Id: 3 }] },
        { type: DELETE_SITE, payload: { id: 2 } }
      ).siteRows
    );

    我试图清理重复的逻辑,但你可以保持原样,解决你的问题的是 map 函数之后的 filter 函数。

    【讨论】:

    • 感谢您的回答!当我执行您的示例代码时,我仍然会遇到一些 React 错误,并且它会崩溃。这些是我得到的错误:“失败的道具类型:无效的道具children提供给ForwardRef(Alert),需要一个ReactNode。” && “对象作为 React 子级无效(发现:TypeError: undefined is not iterable (cannot read property Symbol(Symbol.iterator)))。如果您打算渲染一组子级,请改用数组。” && 无法对未安装的组件执行 React 状态更新。这是一个空操作,但它表明您的应用程序中存在内存泄漏......”有什么想法吗?
    • 我必须说,我添加了一些console.logs,它们都是在“recurCheck”等中触发的,所以它循环通过代码,没问题。但是我猜当它尝试设置“siteRows”属性或执行过滤器时,就会抛出错误?
    • 我已经通过稍微修改您的代码来修复它。我已将您进行“索引”检查(索引> = ...)的位置更改为现在发生在“重复(索引+1)”行之前。我还在检查之前添加了 index+1,而不是在“recur(index +1)”行中。然后就可以了 :) 谢谢你的帮助!
    • @Tempuslight 我没有测试它,但你是对的,应该是if (index >= keys.length - 1) {,不需要其他更改。我添加了一个可测试的 sn-p。
    猜你喜欢
    • 1970-01-01
    • 2018-06-01
    • 2015-07-16
    • 2015-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-17
    相关资源
    最近更新 更多