Skip to content

Commit 0761f60

Browse files
committed
README tweaks
Add TypeScript syntax highlighting to example. Clarify mutation behavior of `.default()`.
1 parent e019cd4 commit 0761f60

File tree

1 file changed

+58
-27
lines changed

1 file changed

+58
-27
lines changed

README.md

Lines changed: 58 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,14 @@ Status](https://travis-ci.org/dphilipson/typescript-fsa-reducers.svg?branch=mast
99
## Introduction
1010

1111
This library will allow you to write typesafe reducers that look like this:
12+
1213
```ts
1314
const reducer = reducerWithInitialState(INITIAL_STATE)
1415
.case(setName, setNameHandler)
1516
.case(addBalance, addBalanceHandler)
1617
.case(setIsFrozen, setIsFrozenHandler);
1718
```
19+
1820
It removes the boilerplate normally associated with writing reducers, including
1921
if-else chains, the default case, and the need to pull the payload field off of
2022
the action.
@@ -49,6 +51,7 @@ top of and assumes familiarity with the excellent
4951

5052
Suppose we have used [typescript-fsa](https://github.com/aikoven/typescript-fsa)
5153
to define our state and some actions:
54+
5255
```ts
5356
import actionCreatorFactory from "typescript-fsa";
5457
const actionCreator = actionCreatorFactory();
@@ -69,7 +72,9 @@ const setName = actionCreator<string>("SET_NAME");
6972
const addBalance = actionCreator<number>("ADD_BALANCE");
7073
const setIsFrozen = actionCreator<boolean>("SET_IS_FROZEN");
7174
```
75+
7276
Using vanilla `typescript-fsa`, we might define a reducer as follows:
77+
7378
```ts
7479
import { Action } from "redux";
7580
import { isType } from "typescript-fsa";
@@ -89,7 +94,9 @@ function reducer(state = INITIAL_STATE, action: Action): State {
8994
}
9095
}
9196
```
97+
9298
Using this library, the above is exactly equivalent to the following code:
99+
93100
```ts
94101
import { reducerWithInitialState } from "typescript-fsa-reducers";
95102

@@ -101,6 +108,7 @@ const reducer = reducerWithInitialState(INITIAL_STATE)
101108
}))
102109
.case(setIsFrozen, (state, isFrozen) => ({ ...state, isFrozen }));
103110
```
111+
104112
Note that unlike the vanilla case, there is no need to pull the payload off of
105113
the action, as it is passed directly to the handler, nor is it necessary to
106114
specify a default case which returns `state` unmodified.
@@ -114,29 +122,37 @@ If the full action is needed rather than just the payload, `.caseWithAction()`
114122
may be used in place of `.case()`. This may be useful if you intend to pass the
115123
action unchanged to a different reducer, or if you need to read the `meta` field
116124
of the action. For example:
125+
117126
```ts
118127
import { Action } from "typescript-fsa";
119128

120129
const setText = actionCreator<string>("SET_TEXT");
121130

122-
const reducer = reducerWithInitialState({ text: "", lastEditBy: "" })
123-
.caseWithAction(incrementCount, (state, { payload, meta }) => ({
124-
text: payload,
125-
lastEditBy: meta.author,
126-
}));
131+
const reducer = reducerWithInitialState({
132+
text: "",
133+
lastEditBy: "",
134+
}).caseWithAction(incrementCount, (state, { payload, meta }) => ({
135+
text: payload,
136+
lastEditBy: meta.author,
137+
}));
127138

128139
// Returns { text: "hello", lastEditBy: "cbrontë" }.
129140
reducer(undefined, setText("hello", { author: "cbrontë" }));
130141
```
142+
131143
Further, a single handler may be assigned to multiple action types at once using
132144
`.cases()` or `.casesWithAction()`:
145+
133146
```ts
134-
const reducer = reducerWithInitialState(initialState)
135-
.cases([setName, addBalance], (state, payload) => {
147+
const reducer = reducerWithInitialState(initialState).cases(
148+
[setName, addBalance],
149+
(state, payload) => {
136150
// Payload has type SetNamePayload | AddBalancePayload.
137151
// ...
138-
});
152+
},
153+
);
139154
```
155+
140156
The reducer builder chains are mutable. Each call to `.case()` modifies the
141157
callee to respond to the specified action type. If this is undesirable, see the
142158
[`.build()`](#build) method below.
@@ -148,11 +164,13 @@ For this library to be useful, you will also need
148164
actions.
149165

150166
With Yarn:
167+
151168
```
152169
yarn add typescript-fsa-reducers typescript-fsa
153170
```
154171

155172
Or with NPM:
173+
156174
```
157175
npm install --save typescript-fsa-reducers typescript-fsa
158176
```
@@ -182,7 +200,8 @@ composing reducers for which initial state is unnecessary.
182200

183201
Note that since the type of the state cannot be inferred from the initial state,
184202
it must be provided as a type parameter:
185-
``` javascript
203+
204+
```javascript
186205
const reducer = reducerWithoutInitialState<State>()
187206
.case(setName, setNameHandler)
188207
.case(addBalance, addBalanceHandler)
@@ -200,7 +219,8 @@ Note that the function produced is technically not a reducer because the initial
200219
and updated states are different type.
201220

202221
Example usage:
203-
``` javascript
222+
223+
```javascript
204224
type State = StoppedState | RunningState;
205225

206226
interface StoppedState {
@@ -267,33 +287,41 @@ entire action unmodified to some other function. For an example, see
267287

268288
Like `.case()`, except that multiple action creators may be provided and the
269289
same handler is applied to all of them. That is,
270-
``` javascript
271-
reducerWithInitialState(initialState)
272-
.cases([setName, addBalance, setIsFrozen], handler);
290+
291+
```javascript
292+
reducerWithInitialState(initialState).cases(
293+
[setName, addBalance, setIsFrozen],
294+
handler,
295+
);
273296
```
297+
274298
is equivalent to
275-
``` javascript
299+
300+
```javascript
276301
reducerWithInitialState(initialState)
277302
.case(setName, handler)
278303
.case(addBalance, handler)
279304
.case(setIsFrozen, handler);
280305
```
306+
281307
Note that the payload passed to the handler may be of the type of any of the
282-
listed action types' payloads. In TypeScript terms, this means it has type `P1 |
283-
P2 | ...`, where `P1, P2, ...` are the payload types of the listed action
308+
listed action types' payloads. In TypeScript terms, this means it has type `P1 | P2 | ...`, where `P1, P2, ...` are the payload types of the listed action
284309
creators.
285310

286311
The payload type is inferred automatically for up to four action types. After
287312
that, it must be supplied as a type annotation, for example:
288-
``` javascript
289-
reducerWithInitialState(initialState)
290-
.cases<{ documentId: number }>([
313+
314+
```javascript
315+
reducerWithInitialState(initialState).cases <
316+
{ documentId: number } >
317+
([
291318
selectDocument,
292319
editDocument,
293320
deleteDocument,
294321
sendDocument,
295-
archiveDocument
296-
], handler)
322+
archiveDocument,
323+
],
324+
handler);
297325
```
298326

299327
#### `.casesWithAction(actionCreators, handler(state, action) => newState)`
@@ -303,13 +331,16 @@ second argument rather than just the payload.
303331

304332
#### `.default(handler(state, action) => newState)`
305333

306-
Mutates the reducer such that it applies `handler` when no previously added `.case()`, `.caseWithAction()`, etc. matched.
307-
The handler is similar to the one in `.caseWithAction()`.
308-
Note that `.default()` ends the chain and internally does the same as [`.build()`](#build), because it is not intended that the chain is mutated after calling `.default()`.
334+
Produces a reducer which applies `handler` when no previously added `.case()`,
335+
`.caseWithAction()`, etc. matched. The handler is similar to the one in
336+
`.caseWithAction()`. Note that `.default()` ends the chain and internally does
337+
the same as [`.build()`](#build), because it is not intended that the chain be
338+
mutated after calling `.default()`.
309339

310-
This is especially useful if you have a nested reducer for some property, that you need to call from the parent reducer on any action:
340+
This is useful if you need a "delegate" reducer should be called on any action
341+
after handling a few specific actions in the parent.
311342

312-
```
343+
```ts
313344
const NESTED_STATE = {
314345
someProp: "hello",
315346
};
@@ -355,7 +386,7 @@ There are two reasons you may want to do this:
355386

356387
Example usage:
357388

358-
``` javascript
389+
```javascript
359390
const reducer = reducerWithInitialState(INITIAL_STATE)
360391
.case(setName, setNameHandler)
361392
.case(addBalance, addBalanceHandler)

0 commit comments

Comments
 (0)