【问题标题】:A state mutation was detected between dispatches, Redux toolkit and selectors/reselect在调度、Redux 工具包和选择器/重新选择之间检测到状态突变
【发布时间】:2021-10-20 19:01:57
【问题描述】:

我在createSelector 和异步重击方面遇到了一些问题。

基本上,我正在尝试检索链接列表,并根据点击次数从最高到最低对它们进行排序。

这是我的简化代码。

MainPage.tsx

export const MainPage = (): JSX.Element => {
  const dispatch = useDispatch();
  const allLinks = useSelector(selectLinks);
  
  useEffect(() => {
    dispatch(getLinks());
  }, [dispatch]);

  return (
    <div>
      {allLinks.map((link) => ()} //unrelated logic
    </div>
  );
};

links.actions.ts

export const getLinks = createAsyncThunk(
  "getLinks",
  async () => {
    const links = await axios.get"/links")
    return links;
  },
);

links.slice.ts

const linksSlice = createSlice({
  name: "data",
  initialState,
  reducers: {},
  extraReducers: (builder) => {
    builder
    .addCase(
      getLinks.fulfilled,
      (state, action) => {
        state.links = action.payload;
      },
    );
  },
});

links.selectors.ts

const selectLinksState = (state: RootState) => state.links;

export const selectLinks = createSelector(selectLinksState, (state) =>
  state.links.sort((a, b) => b.clickCount - a.clickCount),
);

所以编译正常,但是当我在网络浏览器中打开它时,我收到以下错误Error: Invariant failed: A state mutation was detected between dispatches

有谁知道我做错了什么?我很确定这与选择器有关,因为如果我在操作中获取链接后直接对链接进行排序,它就可以正常工作。

【问题讨论】:

    标签: reactjs redux redux-thunk redux-toolkit reselect


    【解决方案1】:

    Sort 使用就地排序算法,它不返回新数组,因此您通过选择器逻辑改变状态。

    Array.prototype.sort

    sort() 方法对数组元素进行就地排序并返回 排序后的数组。默认排序顺序是升序,建立在 将元素转换为字符串,然后比较它们的序列 UTF-16 代码单元值。

    您可以通过内联使用.slice 创建links 数组的副本,然后对 数组引用进行排序:

    export const selectLinks = createSelector(
      [selectLinksState],
      (state) => state.links.slice().sort((a, b) => b.clickCount - a.clickCount),
    );
    

    【讨论】:

    • 谢谢,几分钟前我设法找出原因。感谢您的重申!
    • @ffx292 是的,我大部分时间都在输入答案并看到另一个答案弹出,并希望在提交之前确保我的答案足够不同。没有注意到这是一个自我回答。干杯。
    【解决方案2】:

    所以即使 Redux 工具包是可变的,我还是修改了 reselect 函数并将其更改为:

    export const selectLinks = createSelector(selectLinksState, (state) => {
      const sortedArray = [...state.links].sort(
        (a, b) => b.clickCount - a.clickCount,
      );
      return sortedArray;
    });
    

    我的逻辑是创建一个新数组,这样就不会导致任何突变问题。现在可以正常使用了!

    【讨论】:

      猜你喜欢
      • 2019-12-25
      • 2017-07-17
      • 2019-10-13
      • 2017-04-24
      • 2017-11-04
      • 2018-11-03
      • 1970-01-01
      • 2016-12-08
      • 1970-01-01
      相关资源
      最近更新 更多