I have my reducer
const userAuthSlice = createSlice({
name: "userAuth",
initialState: {
token: '',
},
reducers: {
setToken: (state, action) => state.token = action.payload.test,
},
});
And I have my dispatch command
<button
value={text.sign_in.submit}
onClick={() => dispatch(userAuthSlice.actions.setToken({test:"test"}))}
/>
As I press the button what I get is this error:

I have isolated everything to be sure that this is the problem and nothing else.
Why does this error pop up?
The issue is the use of an arrow function with no curly braces as the reducer, because that acts as an implicit return statement. So, you're both mutating state.token, and returning the result of the assignment.
Per the Immer docs on returning data, there's a couple ways to fix this:
void operator in front of the assignmentso setToken reducer can be updated with void as
setToken: (state, action) => void(state.token = action.payload.test)
Instead of
state.token = action.payload.token
use
const token = action.payload.token
state.token = token
Constants are immutable, and assigning action.payload contents to a constant resolved a problem for me (Note that in case the payload is an object it is not necessary
Working example of createSlice:
import { createSlice } from '@reduxjs/toolkit';
export const slice = createSlice({
name: 'login',
initialState: {
username: "Foo",
password: "AAA",
authorized : false
},
reducers: {
setUsername: (state, action) => {
const value = action.payload
state.username = value // action.payload.username
},
setPassword: (state, action) => {
const value = action.payload
state.password = value // action.payload.password
},
logon: (state, action) => {
state.username = action.payload.username
state.password = action.payload.password
state.authorized = true
},
logoff: state => state.authorized = false
},
});
you may forget break; statement at your reducer.js file;
case LOGIN_USER_ERROR_RESET:
draft.errormsg = '';
draft.loading = false;
draft.error = false;
break;
Points to learn about IMMER
immer will return finalized draft anywayrecipe function then as per point 1, the new return value will replace the stateNow coming to answer for the question. this is your reducer function
(state, action) => state.token = action.payload.test
This function is doing two things,
1. modifying state
2. returning action.payload.test
so it's violating point 4 and hence the error from Immer library
in this specific case, intention is only to modify the state, so we have to undo the existing return with void
setToken: (state, action) => void(state.token = action.payload.test)
However, Immer library recommends the use of code block to insure consistency across large code-base, this code block implicitly returns undefined
setToken: (state, action) => { state.token = action.payload.test }
Try checking this link for Copying Without Reference
Correct answer
Use Instead of
const userAuthSlice = createSlice({
name: "userAuth",
initialState: {
token: '',
},
reducers: {
setToken: (state, action) => state.token = action.payload.test,
},
});
Use this {I have just added brackets}
const userAuthSlice = createSlice({
name: "userAuth",
initialState: {
token: '',
},
reducers: {
setToken: (state, action) => { state.token = action.payload.test}, // <<= Change Here
},
});
For those who are working with React PullState, my issue was with the syntax:
I had:
const onUpdate = (value: any) => {
someStore.update((s) => (s.value = value));
};
but has to be:
const onUpdate = (value: any) => {
someStore.update((s) => {
s.value = value;
});
};
For some reason, doesn't like the arrow function declared on the first approach.