簡體   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