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@nextChangelog
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