Skip to content

Commit 88f3b4b

Browse files
committed
future plans
1 parent 01c30b9 commit 88f3b4b

File tree

1 file changed

+110
-1
lines changed

1 file changed

+110
-1
lines changed

docs/migrations/1.x-to-2.x.md

Lines changed: 110 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -708,8 +708,117 @@ yield takeEvery(todoAdded.type, saga)
708708

709709
### Custom slice reducer creators
710710

711-
### Selector factories
711+
With the addition of the [callback syntax for createSlice](#callback-syntax-for-createslicereducers), the [suggestion](https://github.com/reduxjs/redux-toolkit/issues/3837) was made to enable custom slice reducer creators. These creators would be able to:
712+
713+
- Modify reducer behaviour by adding case or matcher reducers
714+
- Attach actions (or any other useful functions) to `slice.actions`
715+
- Attach provided case reducers to `slice.caseReducers`
716+
717+
The creator would need to first return a "definition" shape when `createSlice` is first called, which it then handles by adding any necessary reducers and/or actions.
718+
719+
An API for this is not set in stone, but the existing `create.asyncThunk` creator implemented with a potential API could look like:
720+
721+
```js
722+
const asyncThunkCreator = {
723+
type: ReducerType.asyncThunk,
724+
define(payloadCreator, config) {
725+
return {
726+
type: ReducerType.asyncThunk, // needs to match reducer type, so correct handler can be called
727+
payloadCreator,
728+
...config,
729+
}
730+
},
731+
handle(
732+
{
733+
// the key the reducer was defined under
734+
reducerName,
735+
// the autogenerated action type, i.e. `${slice.name}/${reducerName}`
736+
type,
737+
},
738+
// the definition from define()
739+
definition,
740+
// methods to modify slice
741+
context
742+
) {
743+
const { payloadCreator, options, pending, fulfilled, rejected, settled } =
744+
definition
745+
const asyncThunk = createAsyncThunk(type, payloadCreator, options)
746+
747+
if (pending) context.addCase(asyncThunk.pending, pending)
748+
if (fulfilled) context.addCase(asyncThunk.fulfilled, fulfilled)
749+
if (rejected) context.addCase(asyncThunk.rejected, rejected)
750+
if (settled) context.addMatcher(asyncThunk.settled, settled)
751+
752+
context.exposeAction(reducerName, asyncThunk)
753+
context.exposeCaseReducer(reducerName, {
754+
pending: pending || noop,
755+
fulfilled: fulfilled || noop,
756+
rejected: rejected || noop,
757+
settled: settled || noop,
758+
})
759+
},
760+
}
761+
762+
const createSlice = buildCreateSlice({
763+
creators: {
764+
asyncThunk: asyncThunkCreator,
765+
},
766+
})
767+
768+
const todoSlice = createSlice({
769+
name: 'todos',
770+
})
771+
```
772+
773+
We're not sure how many people/libraries would actually make use of this though, so any feedback over on the [Github issue](https://github.com/reduxjs/redux-toolkit/issues/3837) is welcome!
774+
775+
### `createSlice.selector` selector factories
776+
777+
There have been some concerns raised internally about whether `createSlice.selectors` supports memoized selectors sufficiently. You can provide a memoized selector to your `createSlice.selectors` configuration, but you're stuck with that one instance.
778+
779+
```ts
780+
const todoSlice = createSlice({
781+
name: 'todos',
782+
initialState: {
783+
todos: [] as Todo[],
784+
},
785+
reducers: {},
786+
selectors: {
787+
selectTodosByAuthor = createSelector(
788+
(state: TodoState) => state.todos,
789+
(state: TodoState, author: string) => author,
790+
(todos, author) => todos.filter((todo) => todo.author === author)
791+
),
792+
},
793+
})
794+
795+
export const { selectTodosByAuthor } = todoSlice.selectors
796+
```
797+
798+
With `reselect`'s default cache size of 1, this can cause caching issues if called in multiple components with different arguments. One typical solution for this (without `createSlice`) is a [selector factory](https://redux.js.org/usage/deriving-data-selectors#creating-unique-selector-instances):
799+
800+
```ts
801+
export const makeSelectTodosByAuthor = () =>
802+
createSelector(
803+
(state: RootState) => state.todos.todos,
804+
(state: RootState, author: string) => author,
805+
(todos, author) => todos.filter((todo) => todo.author === author)
806+
)
807+
808+
function AuthorTodos({ author }: { author: string }) {
809+
const selectTodosByAuthor = useMemo(makeSelectTodosByAuthor, [])
810+
const todos = useSelector((state) => selectTodosByAuthor(state, author))
811+
}
812+
```
813+
814+
Of course, with `createSlice.selectors` this is no longer possible, as you need the selector instance when creating your slice.
815+
816+
In 2.0.0 we have no set solution for this - a few APIs have been floated ([PR 1](https://github.com/reduxjs/redux-toolkit/pull/3671), [PR 2](https://github.com/reduxjs/redux-toolkit/pull/3836)) but nothing was decided upon. If this is something you'd like to see supported, consider providing feedback in the [Github discussion](https://github.com/reduxjs/redux-toolkit/discussions/3387)!
712817

713818
### 3.0 - RTK Query
714819

820+
RTK 2.0 was largely focused on core and toolkit changes. Now that 2.0 is released, we would like to shift our focus to RTK Query, as there is still some rough edges to iron out - some of which may require breaking changes, necessitating a 3.0 release.
821+
822+
If you have any feedback for what that could look like, please consider chiming in at the [RTK Query API pain points and rough spots feedback thread](https://github.com/reduxjs/redux-toolkit/issues/3692)!
823+
715824
</div>

0 commit comments

Comments
 (0)