繁体   English   中英

在调度、Redux 工具包和选择器/重新选择之间检测到 state 突变

[英]A state mutation was detected between dispatches, Redux toolkit and selectors/reselect

我在createSelector和 async thunk 方面遇到了一些麻烦。

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

这是我的简化代码。

主页.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>
  );
};

链接.actions.ts

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

链接.slice.ts

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

链接选择器.ts

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

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

所以这个编译很好,但是当我在 web 浏览器中打开它时,我收到以下错误Error: Invariant failed: A state mutation was detected between dispatches

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

因此,即使 Redux 工具包是可变的,我还是修改了重新选择 function 并将其更改为:

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

我的逻辑是创建一个新数组,这样它就不会引起任何突变问题。 现在工作正常!

Sort 使用就地排序算法,它不返回新数组,因此您正在通过选择器逻辑对 state 进行变异。

数组原型排序

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

您可以使用.slice in-line 创建links数组的副本,然后对数组引用进行排序:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM