From 99664803777882488348d9212bc18de92dcde05c Mon Sep 17 00:00:00 2001 From: Lenz Weber Date: Sun, 1 Dec 2019 22:59:42 +0100 Subject: [PATCH] =?UTF-8?q?document=20alternative=20callback-builder-style?= =?UTF-8?q?=20notation=20for=20actions=E2=80=A6=20(#268)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * alternative callback-builder-style notation for actionsMap * Clarify builder usage purpose * Fix formatting and wording * Fix TS usage in createSlice example --- docs/api/createReducer.md | 16 +++++++++++++++ docs/api/createSlice.md | 30 ++++++++++++++++++++++------- docs/usage/usage-with-typescript.md | 24 +++++++++++------------ package-lock.json | 2 +- 4 files changed, 51 insertions(+), 21 deletions(-) diff --git a/docs/api/createReducer.md b/docs/api/createReducer.md index 7451fa8078..fb502fa42e 100644 --- a/docs/api/createReducer.md +++ b/docs/api/createReducer.md @@ -49,6 +49,22 @@ const counterReducer = createReducer(0, { }) ``` +### The "builder callback" API + +Instead of using a simple object as an argument to `createReducer`, you can also provide a callback that receives an `ActionReducerMapBuilder` instance: + +```typescript +createReducer(0, builder => + builder.add(increment, (state, action) => { + // action is inferred correctly here + }) +) +``` + +This is intended for use with TypeScript, as passing a plain object full of reducer functions cannot infer their types correctly in this case. It has no real benefit when used with plain JS. + +We recommend using this API if stricter type safety is necessary when defining reducer argument objects. + ## Direct State Mutation Redux requires reducer functions to be pure and treat state values as immutable. While this is essential for making state updates predictable and observable, it can sometimes make the implementation of such updates awkward. Consider the following example: diff --git a/docs/api/createSlice.md b/docs/api/createSlice.md index 6d97b59f47..21ca97fa81 100644 --- a/docs/api/createSlice.md +++ b/docs/api/createSlice.md @@ -23,7 +23,9 @@ function createSlice({ // A name, used in action types name: string, // An additional object of "case reducers". Keys should be other action types. - extraReducers?: Object + extraReducers?: + | Object + | ((builder: ActionReducerMapBuilder) => void) }) ``` @@ -71,6 +73,12 @@ Action creators that were generated using [`createAction`](./createAction.md) ma computed property syntax. (If you are using TypeScript, you may have to use `actionCreator.type` or `actionCreator.toString()` to force the TS compiler to accept the computed property.) +### The "builder callback" API for `extraReducers` + +Instead of using a simple object as `extraReducers`, you can also use a callback that receives a `ActionReducerMapBuilder` instance. + +We recommend using this API if stricter type safety is necessary when defining reducer argument objects. + ## Return Value `createSlice` will return an object that looks like: @@ -103,21 +111,28 @@ for references in a larger codebase. ## Examples -```js -import { createSlice } from '@reduxjs/toolkit' +```ts +import { createSlice, createAction, PayloadAction } from '@reduxjs/toolkit' import { createStore, combineReducers } from 'redux' +const incrementBy = createAction('incrementBy') + const counter = createSlice({ name: 'counter', - initialState: 0, + initialState: 0 as number, reducers: { increment: state => state + 1, decrement: state => state - 1, multiply: { - reducer: (state, action) => state * action.payload, - prepare: value => ({ payload: value || 2 }) // fallback if the payload is a falsy value + reducer: (state, action: PayloadAction) => state * action.payload, + prepare: (value: number) => ({ payload: value || 2 }) // fallback if the payload is a falsy value } - } + }, + // "builder callback API" + extraReducers: builder => + builder.add(incrementBy, (state, action) => { + return state + action.payload + }) }) const user = createSlice({ @@ -128,6 +143,7 @@ const user = createSlice({ state.name = action.payload // mutate the state all you want with immer } }, + // "map object API" extraReducers: { [counter.actions.increment]: (state, action) => { state.age += 1 diff --git a/docs/usage/usage-with-typescript.md b/docs/usage/usage-with-typescript.md index 0f44d3519c..3bc583fa9b 100644 --- a/docs/usage/usage-with-typescript.md +++ b/docs/usage/usage-with-typescript.md @@ -142,19 +142,17 @@ As an alternative, RTK includes a type-safe reducer builder API. Instead of using a simple object as an argument to `createReducer`, you can also use a callback that receives a `ActionReducerMapBuilder` instance: ```typescript -{ - const increment = createAction('increment') - const decrement = createAction('decrement') - createReducer(0, builder => - builder - .add(increment, (state, action) => { - // action is inferred correctly here - }) - .add(decrement, (state, action: PayloadAction) => { - // this would error out - }) - ) -} +const increment = createAction('increment') +const decrement = createAction('decrement') +createReducer(0, builder => + builder + .add(increment, (state, action) => { + // action is inferred correctly here + }) + .add(decrement, (state, action: PayloadAction) => { + // this would error out + }) +) ``` We recommend using this API if stricter type safety is necessary when defining reducer argument objects. diff --git a/package-lock.json b/package-lock.json index e582916cd2..6a9f6efa87 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "redux-toolkit", + "name": "@reduxjs/toolkit", "version": "1.0.4", "lockfileVersion": 1, "requires": true,