v2.0.0-rc.0
Pre-releaseThis release candidate modifies the approach for defining async thunks inside of createSlice
, and improves several bits of usage and implementation around selectors.
Note that we hope to release Redux Toolkit 2.0, Redux core 5.0, and React-Redux 9.0 by the start of December! (If we don't hit that, we'll aim for January, after the holidays.)
See the preview Redux Toolkit 2.0 + Redux core 5.0 Migration Guide for an overview of breaking changes in RTK 2.0 and Redux core.
The 2.0 integration branch contains the docs preview for the 2.0 changes. Not all changes are documented yet, but you can see API reference pages for most of the new features here:
npm install @reduxjs/toolkit@next
yarn add @reduxjs/toolkit@next
Changelog
Async Thunk and createSlice
changes
In earlier alphas, we added the ability to define async thunks directly inside of createSlice.reducers
, using a callback syntax. However, that meant that createSlice
had a hard dependency on createAsyncThunk
, and importing createSlice
would always include createAsyncThunk
in an app bundle even if it wasn't being used.
In practice, we expect that most RTK users will use createAsyncThunk
, either directly or as part of RTK Query. But, we take bundle size seriously, and didn't want to force all uses of createSlice
to add the 2K for createAsyncThunk
to a bundle if it isn't actually being used.
Since we expect that defining thunks inside of createSlice
is a less-common use case, we've settled on a compromise. The standard createSlice
method does not support calling create.asyncThunk()
inside even if you use the callback syntax. Instead, you need to call buildCreateSlice()
to create a customized version of createSlice
with the async thunk capabilities built in, and use that:
const createSliceWithThunks = buildCreateSlice({
creators: { asyncThunk: asyncThunkCreator },
})
const todosSlice = createSliceWithThunks ({
name: 'todos',
initialState: {
loading: false,
todos: [],
error: null,
} as TodoState,
reducers: (create) => ({
// A normal "case reducer", same as always
deleteTodo: create.reducer((state, action: PayloadAction<number>) => {
state.todos.splice(action.payload, 1)
}),
// A case reducer with a "prepare callback" to customize the action
addTodo: create.preparedReducer(
(text: string) => {
const id = nanoid()
return { payload: { id, text } }
},
// action type is inferred from prepare callback
(state, action) => {
state.todos.push(action.payload)
}
),
// An async thunk
fetchTodo: create.asyncThunk(
// Async payload function as the first argument
async (id: string, thunkApi) => {
const res = await fetch(`myApi/todos?id=${id}`)
return (await res.json()) as Item
},
// An object containing `{pending?, rejected?, fulfilled?, settled?, options?}` second
{
pending: (state) => {
state.loading = true
},
rejected: (state, action) => {
state.error = action.payload ?? action.error
},
fulfilled: (state, action) => {
state.todos.push(action.payload)
},
// settled is called for both rejected and fulfilled actions
settled: (state, action) => {
state.loading = false
},
}
),
}),
})
Selector Changes
createSlice
now adds a selectSlice
field to all slice objects. This simple selector assumes that the slice has been added at rootState[slice.name]
(or rootState[slice.reducerPath]
if defined). This is useful for basic lookups of the slice's state.
entityAdapter.getSelectors()
now accepts alternate selector creators with customized memoization options.
What's Changed
- [RTK v2.0] output selector fields are currently missing in selector functions created using
createDraftSafeSelector
. by @aryaemami59 in #3722 - createDynamicMiddleware bike shedding by @EskiMojo14 in #3763
- Allow passing selector creators with different memoize options to getSelectors by @EskiMojo14 in #3833
- Add selectSlice to slice instance by @EskiMojo14 in #3838
- Throw an error if ApiProvider is nested inside a normal Provider. by @EskiMojo14 in #3855
- Create standardised methods of modifying reducer handler context. by @EskiMojo14 in #3872
- Require calling buildCreateSlice to use create.asyncThunk by @EskiMojo14 in #3867
- Restore the toString override, but keep it out of the docs. by @EskiMojo14 in #3877
- Selector housekeeping - emplace and unwrapped by @EskiMojo14 in #3878
- Update deps for RC by @markerikson in #3883
Full Changelog: v2.0.0-beta.4...v2.0.0-rc.0