I am fairly new to redux and reduxjs/toolkit and I'm stuck on updating the state after a successful api call. I'm following along with the docs here -> https://redux-toolkit.js.org/api/createAsyncThunk
import { createSlice } from '@reduxjs/toolkit';
import { loginUser } from './actions';
const userSlice = createSlice({
name: 'user',
initialState: { id: 0, name: '', email: '' },
reducers: {},
extraReducers: (builder) => {
builder.addCase(loginUser.fulfilled, (state, action) => {
// trying to overwrite the state directly like this doesn't work
state = { ...action.payload }
// updating each individual part of the state object does work, but this is not ideal for scalability
// state.id = action.payload.id;
// state.name = action.payload.name;
// state.email = action.payload.email;
});
},
As indicated in the comments, attempting to overwrite the entire state object does not work. No error messages, but nothing happens. However, updating each individual part of the state object does work.
CodePudding user response:
Redux Toolkit is built on top of Immer. Immer lets you update the state in two ways.
Important: be careful you choose one or the other, never both.
1. Mutate state
builder.addCase(loginUser.fulfilled, (state, action) => {
state.id = action.payload.id;
state.name = action.payload.name;
state.email = action.payload.email;
// NEVER use return when mutating state
});
2. Return new state
builder.addCase(loginUser.fulfilled, (state, action) => {
// NEVER mutate state when using return
return {
id: action.payload.id,
name: action.payload.name,
email: action.payload.email,
};
});
The return syntax could simplify to the following:
builder.addCase(loginUser.fulfilled, (state, action) => action.payload);
But I do not recommend it. I think you're better off being explicit about the state changes in your reducers. It makes it easier to understand what changes are taking place.