The following code works as intended. The state gets populated using the createEntityAdapter.
import { createSlice, createAsyncThunk, createEntityAdapter } from '@reduxjs/toolkit';
export const fetchUsers = createAsyncThunk('users/fetchUsers', async () => {
const response = await fetch('https://mysite/wp-json/wp/v2/users');
return response.json();
});
export const usersAdapter = createEntityAdapter();
const initialState = usersAdapter.getInitialState({ status: 'idle' });
export const usersSlice = createSlice({
name: 'users',
initialState,
reducers: {},
extraReducers: (builder) => {
builder.addCase(fetchUsers.pending, (state) => {
state.status = 'pending';
});
builder.addCase(fetchUsers.fulfilled, usersAdapter.upsertMany);
},
});
export default usersSlice.reducer;
However, with the fulfilled promise, I also want to update the 'status' property of the state to 'idle'.
When I change the fulfilled case to:
builder.addCase(fetchUsers.fulfilled, (state, action) => {
usersAdapter.upsertMany;
state.status = 'idle';
});
And when I get add an argument the upsertMany
builder.addCase(fetchUsers.fulfilled, (state, action) => {
usersAdapter.upsertMany(action.payload);
state.status = 'idle';
});
I get the error: Possible unhandled Promise Rejection (id: 0)
Apart from the question how to make it work, could I ask one additional question? In the first code snippet (That one that works):
builder.addCase(fetchUsers.fulfilled, usersAdapter.upsertMany);
I understand that the addCase has two arguments: action type/creator (fetchUsers.fulfilled is the action creator here), and a reducer (usersAdapter.upsertMany in this case). Here fetchUsers returns the object, but how does usersAdapter.upsertMany know what to insert/update as payload? There's no argument there (eg. usersAdapter.upsertMany(action.payload). In all other reducers requiring some payload, there's always an argument (state, action) eg.
builder.addCase(incrementBy, (state, action) => state.counter += action.payload)