![](/img/trans.png)
[英]React & Redux, Update state, Error: A state mutation was detected between dispatches
[英]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.