I'm having some trouble regarding createSelector
and async thunk.
Basically I'm trying to retrieve a list of links, and sort them depending on how many clicks they have, from highest to lowest.
Here is my simplified code.
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),
);
So this compiles fine, but when I open it in the web browser, I get the following error Error: Invariant failed: A state mutation was detected between dispatches
Does anyone know what I'm doing wrong? I'm pretty sure it's something to do with the selectors because if I sort the links directly after fetching them in the action, it works fine.
So even though Redux toolkit is mutable, I tinkered around with the reselect function and changed it to so:
export const selectLinks = createSelector(selectLinksState, (state) => {
const sortedArray = [...state.links].sort(
(a, b) => b.clickCount - a.clickCount,
);
return sortedArray;
});
My logic was to create a new array, so that it wouldn't cause any mutation problems. It works fine now!