I'm working on my project @reduxjs/toolkit
and created UserSlice
like below.
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import { User } from "../../models";
export type UserState = User | null;
export const initialUserState: UserState = null;
const UserSlice = createSlice({
name: "User",
initialState: initialUserState,
reducers: {
receiveUser: (state: UserState, action: PayloadAction<UserState>) => {
state = action.payload;
},
clearUser: (state: UserState, _action: PayloadAction<void>) => {
state = null;
},
signIn: (
_,
_action: PayloadAction<{
email: string;
password: string;
}>
) => {},
signInWithToken: (_, _action: PayloadAction<void>) => {},
},
});
export default UserSlice;
signIn
signInWithToken
are action creators just for taking actions in UserSaga
module, so they do nothing.
When I dispatch signIn
action, below error occurs.
index.js:1 Error: A case reducer on a non-draftable value must not return undefined
at createReducer.ts:163
at Array.reduce (<anonymous>)
at createReducer.ts:143
...
This code snippets pattern works fine my other projects, but this project. I can't figure out the reason of this error, so I'm asking this question. Are there any faults in my code?
Redux Toolkit's createReducer()
allows writing reducers that directly mutate the state. This works by wrapping the reducer call with produce
from the Immer library.
However, the reducer call isn't wrapped with produce
when the current state isn't "draftable" by Immer, which is the case for primitive values, including null
:
} else if (!isDraftable(previousState)) {
// If state is not draftable (ex: a primitive, such as 0), we want to directly
// return the caseReducer func and not wrap it with produce.
const result = caseReducer(previousState as any, action)
if (typeof result === 'undefined') {
throw Error(
'A case reducer on a non-draftable value must not return undefined'
)
}
return result
}
Because your initial User state is null
, you must return the new state from your receiveUser()
reducer.
I believe you're not returning the state in all of your reducers, because when using arrow functions objects need additional round brackets:
reducers: {
receiveUser: (state: UserState, action: PayloadAction<UserState>) => ({
state: action.payload;
}),
clearUser: (state: UserState, _action: PayloadAction<void>) => ({
state : null;
}),
signIn: (
_,
_action: PayloadAction<{
email: string;
password: string;
}>
) => ({}),
signInWithToken: (_, _action: PayloadAction<void>) => ({}),
},
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With