Skip to content

Commit a99796b

Browse files
vinnymacyangmillstheory
authored andcommitted
fix #152 improve documentation (#222)
close #152, #172, #204
1 parent e170d6a commit a99796b

20 files changed

+782
-272
lines changed

.bookignore

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
src/
2+
build/
3+
package.json
4+
webpack*

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,6 @@ es
55
lib
66
dist
77
.idea
8+
9+
# docs generated files
10+
_book

.npmignore

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# doc folders
2+
docs
3+
_book
4+
.bookignore
5+
book.json

CNAME

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
redux-actions.js.org

README.md

+26-271
Original file line numberDiff line numberDiff line change
@@ -6,258 +6,38 @@
66

77
[Flux Standard Action](https://github.com/acdlite/flux-standard-action) utilities for Redux.
88

9-
## Installation
10-
11-
```bash
12-
npm install --save redux-actions
13-
```
14-
15-
The [npm](https://www.npmjs.com) package provides a [CommonJS](http://webpack.github.io/docs/commonjs.html) build for use in Node.js, and with bundlers like [Webpack](http://webpack.github.io/) and [Browserify](http://browserify.org/). It also includes an [ES modules](http://jsmodules.io/) build that works well with [Rollup](http://rollupjs.org/) and [Webpack2](https://webpack.js.org)'s tree-shaking.
16-
17-
If you don’t use [npm](https://www.npmjs.com), you may grab the latest [UMD](https://unpkg.com/redux-actions@latest/dist) build from [unpkg](https://unpkg.com) (either a [development](https://unpkg.com/redux-actions@latest/dist/redux-actions.js) or a [production](https://unpkg.com/redux-actions@latest/dist/redux-actions.min.js) build). The UMD build exports a global called `window.ReduxActions` if you add it to your page via a `<script>` tag. We *don’t* recommend UMD builds for any serious application, as most of the libraries complementary to Redux are only available on [npm](https://www.npmjs.com/search?q=redux).
18-
19-
## Usage
20-
21-
### `createAction(type, payloadCreator = Identity, ?metaCreator)`
22-
23-
```js
24-
import { createAction } from 'redux-actions';
25-
```
26-
27-
Wraps an action creator so that its return value is the payload of a Flux Standard Action.
28-
29-
`payloadCreator` must be a function, `undefined`, or `null`. If `payloadCreator` is `undefined` or `null`, the identity function is used.
30-
31-
Example:
32-
33-
```js
34-
let noop = createAction('NOOP', amount => amount);
35-
// same as
36-
noop = createAction('NOOP');
37-
38-
expect(noop(42)).to.deep.equal({
39-
type: 'NOOP',
40-
payload: 42
41-
});
42-
```
43-
44-
If the payload is an instance of an [Error
45-
object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error),
46-
redux-actions will automatically set ```action.error``` to true.
47-
48-
Example:
49-
50-
```js
51-
const noop = createAction('NOOP');
52-
53-
const error = new TypeError('not a number');
54-
expect(noop(error)).to.deep.equal({
55-
type: 'NOOP',
56-
payload: error,
57-
error: true
58-
});
59-
```
60-
61-
`createAction` also returns its `type` when used as type in `handleAction` or `handleActions`.
62-
63-
Example:
64-
65-
```js
66-
const noop = createAction('INCREMENT');
67-
68-
// As parameter in handleAction:
69-
handleAction(noop, {
70-
next(state, action) {...},
71-
throw(state, action) {...}
72-
});
73-
74-
// As object key in handleActions:
75-
const reducer = handleActions({
76-
[noop]: (state, action) => ({
77-
counter: state.counter + action.payload
78-
})
79-
}, { counter: 0 });
80-
```
81-
82-
**NOTE:** The more correct name for this function is probably `createActionCreator()`, but that seems a bit redundant.
83-
84-
Use the identity form to create one-off actions:
85-
86-
```js
87-
createAction('ADD_TODO')('Use Redux');
88-
```
89-
90-
`metaCreator` is an optional function that creates metadata for the payload. It receives the same arguments as the payload creator, but its result becomes the meta field of the resulting action. If `metaCreator` is undefined or not a function, the meta field is omitted.
91-
92-
### `createActions(?actionMap, ?...identityActions)`
93-
94-
```js
95-
import { createActions } from 'redux-actions';
96-
```
97-
98-
Returns an object mapping action types to action creators. The keys of this object are camel-cased from the keys in `actionMap` and the string literals of `identityActions`; the values are the action creators.
99-
100-
`actionMap` is an optional object and a recursive data structure, with action types as keys, and whose values **must** be either
101-
102-
- a function, which is the payload creator for that action
103-
- an array with `payload` and `meta` functions in that order, as in [`createAction`](#createactiontype-payloadcreator--identity-metacreator)
104-
- `meta` is **required** in this case (otherwise use the function form above)
105-
- an `actionMap`
106-
107-
`identityActions` is an optional list of positional string arguments that are action type strings; these action types will use the identity payload creator.
108-
109-
110-
```js
111-
const { actionOne, actionTwo, actionThree } = createActions({
112-
// function form; payload creator defined inline
113-
ACTION_ONE: (key, value) => ({ [key]: value }),
114-
115-
// array form
116-
ACTION_TWO: [
117-
(first) => [first], // payload
118-
(first, second) => ({ second }) // meta
119-
],
120-
121-
// trailing action type string form; payload creator is the identity
122-
}, 'ACTION_THREE');
9+
### Table of Contents
10+
* [Getting Started](#gettingstarted)
11+
* [Installation](#installation)
12+
* [Usage](#usage)
13+
* [Documentation](#documentation)
12314

124-
expect(actionOne('key', 1)).to.deep.equal({
125-
type: 'ACTION_ONE',
126-
payload: { key: 1 }
127-
});
128-
129-
expect(actionTwo('first', 'second')).to.deep.equal({
130-
type: 'ACTION_TWO',
131-
payload: ['first'],
132-
meta: { second: 'second' }
133-
});
134-
135-
expect(actionThree(3)).to.deep.equal({
136-
type: 'ACTION_THREE',
137-
payload: 3,
138-
});
139-
```
140-
141-
If `actionMap` has a recursive structure, its leaves are used as payload and meta creators, and the action type for each leaf is the combined path to that leaf:
142-
143-
```js
144-
const actionCreators = createActions({
145-
APP: {
146-
COUNTER: {
147-
INCREMENT: [
148-
amount => ({ amount }),
149-
amount => ({ key: 'value', amount })
150-
],
151-
DECREMENT: amount => ({ amount: -amount }),
152-
SET: undefined // given undefined, the identity function will be used
153-
},
154-
NOTIFY: [
155-
(username, message) => ({ message: `${username}: ${message}` }),
156-
(username, message) => ({ username, message })
157-
]
158-
}
159-
});
160-
161-
expect(actionCreators.app.counter.increment(1)).to.deep.equal({
162-
type: 'APP/COUNTER/INCREMENT',
163-
payload: { amount: 1 },
164-
meta: { key: 'value', amount: 1 }
165-
});
166-
expect(actionCreators.app.counter.decrement(1)).to.deep.equal({
167-
type: 'APP/COUNTER/DECREMENT',
168-
payload: { amount: -1 }
169-
});
170-
expect(actionCreators.app.counter.set(100)).to.deep.equal({
171-
type: 'APP/COUNTER/SET',
172-
payload: 100
173-
});
174-
expect(actionCreators.app.notify('yangmillstheory', 'Hello World')).to.deep.equal({
175-
type: 'APP/NOTIFY',
176-
payload: { message: 'yangmillstheory: Hello World' },
177-
meta: { username: 'yangmillstheory', message: 'Hello World' }
178-
});
179-
```
180-
When using this form, you can pass an object with key `namespace` as the last positional argument (the default is `/`).
181-
182-
### `handleAction(type, reducer | reducerMap = Identity, defaultState)`
183-
184-
```js
185-
import { handleAction } from 'redux-actions';
186-
```
18715

188-
Wraps a reducer so that it only handles Flux Standard Actions of a certain type.
16+
# Getting Started {#gettingstarted}
18917

190-
If a `reducer` function is passed, it is used to handle both normal actions and failed actions. (A failed action is analogous to a rejected promise.) You can use this form if you know a certain type of action will never fail, like the increment example above.
191-
192-
Otherwise, you can specify separate reducers for `next()` and `throw()` using the `reducerMap` form. This API is inspired by the ES6 generator interface.
18+
## Installation
19319

194-
```js
195-
handleAction('FETCH_DATA', {
196-
next(state, action) {...},
197-
throw(state, action) {...}
198-
}, defaultState);
20+
```bash
21+
$ npm install --save redux-actions
19922
```
20023

201-
If either `next()` or `throw()` are `undefined` or `null`, then the identity function is used for that reducer.
202-
203-
If the reducer argument (`reducer | reducerMap`) is `undefined`, then the identity function is used.
204-
205-
The third parameter `defaultState` is required, and is used when `undefined` is passed to the reducer.
24+
or
20625

207-
### `handleActions(reducerMap, defaultState, )`
208-
209-
```js
210-
import { handleActions } from 'redux-actions';
21126
```
212-
213-
Creates multiple reducers using `handleAction()` and combines them into a single reducer that handles multiple actions. Accepts a map where the keys are passed as the first parameter to `handleAction()` (the action type), and the values are passed as the second parameter (either a reducer or reducer map). The map must not be empty.
214-
215-
If `reducerMap` has a recursive structure, its leaves are used as reducers, and the action type for each leaf is the path to that leaf. If a node's only children are `next()` and `throw()`, the node will be treated as a reducer. If the leaf is `undefined` or `null`, the identity function is used as the reducer. Otherwise, the leaf should be the reducer function. When using this form, you can pass an object with key `namespace` as the last positional argument (the default is `/`).
216-
217-
The second parameter `defaultState` is required, and is used when `undefined` is passed to the reducer.
218-
219-
(Internally, `handleActions()` works by applying multiple reducers in sequence using [reduce-reducers](https://github.com/acdlite/reduce-reducers).)
220-
221-
Example:
222-
223-
```js
224-
const reducer = handleActions({
225-
INCREMENT: (state, action) => ({
226-
counter: state.counter + action.payload
227-
}),
228-
229-
DECREMENT: (state, action) => ({
230-
counter: state.counter - action.payload
231-
})
232-
}, { counter: 0 });
27+
$ yarn add redux-actions
23328
```
23429

235-
### `combineActions(...types)`
30+
The [npm](https://www.npmjs.com) package provides a [CommonJS](http://webpack.github.io/docs/commonjs.html) build for use in Node.js, and with bundlers like [Webpack](http://webpack.github.io/) and [Browserify](http://browserify.org/). It also includes an [ES modules](http://jsmodules.io/) build that works well with [Rollup](http://rollupjs.org/) and [Webpack2](https://webpack.js.org)'s tree-shaking.
23631

237-
Combine any number of action types or action creators. `types` is a list of positional arguments which can be action type strings, symbols, or action creators.
32+
The [UMD](https://unpkg.com/redux-actions@latest/dist) build exports a global called `window.ReduxActions` if you add it to your page via a `<script>` tag. We *don’t* recommend UMD builds for any serious application, as most of the libraries complementary to Redux are only available on [npm](https://www.npmjs.com/search?q=redux).
23833

239-
This allows you to reduce multiple distinct actions with the same reducer.
34+
## Usage
24035

24136
```js
242-
const { increment, decrement } = createActions({
243-
INCREMENT: amount => ({ amount }),
244-
DECREMENT: amount => ({ amount: -amount }),
245-
})
246-
247-
const reducer = handleAction(combineActions(increment, decrement), {
248-
next: (state, { payload: { amount } }) => ({ ...state, counter: state.counter + amount }),
249-
throw: state => ({ ...state, counter: 0 }),
250-
}, { counter: 10 })
251-
252-
expect(reducer(undefined, increment(1)).to.deep.equal({ counter: 11 })
253-
expect(reducer(undefined, decrement(1)).to.deep.equal({ counter: 9 })
254-
expect(reducer(undefined, increment(new Error)).to.deep.equal({ counter: 0 })
255-
expect(reducer(undefined, decrement(new Error)).to.deep.equal({ counter: 0 })
256-
```
37+
import { createActions, handleActions, combineActions } from 'redux-actions'
25738

258-
Here's an example using `handleActions`:
39+
const defaultState = { counter: 10 };
25940

260-
```js
26141
const { increment, decrement } = createActions({
26242
INCREMENT: amount => ({ amount }),
26343
DECREMENT: amount => ({ amount: -amount })
@@ -267,43 +47,18 @@ const reducer = handleActions({
26747
[combineActions(increment, decrement)](state, { payload: { amount } }) {
26848
return { ...state, counter: state.counter + amount };
26949
}
270-
}, { counter: 10 });
271-
272-
expect(reducer({ counter: 5 }, increment(5))).to.deep.equal({ counter: 10 });
273-
expect(reducer({ counter: 5 }, decrement(5))).to.deep.equal({ counter: 0 });
274-
expect(reducer({ counter: 5 }, { type: 'NOT_TYPE', payload: 1000 })).to.equal({ counter: 5 });
275-
expect(reducer(undefined, increment(5))).to.deep.equal({ counter: 15 });
276-
```
277-
278-
## Usage with middleware
279-
280-
redux-actions is handy all by itself, however, its real power comes when you combine it with middleware.
281-
282-
The identity form of `createAction` is a great way to create a single action creator that handles multiple payload types. For example, using [redux-promise](https://github.com/acdlite/redux-promise) and [redux-rx](https://github.com/acdlite/redux-rx):
283-
284-
```js
285-
const addTodo = createAction('ADD_TODO');
286-
287-
// A single reducer...
288-
handleAction('ADD_TODO', (state = { todos: [] }, action) => ({
289-
...state,
290-
todos: [...state.todos, action.payload]
291-
}));
50+
}, defaultState);
29251

293-
// ...that works with all of these forms:
294-
// (Don't forget to use `bindActionCreators()` or equivalent.
295-
// I've left that bit out)
296-
addTodo('Use Redux')
297-
addTodo(Promise.resolve('Weep with joy'));
298-
addTodo(Observable.of(
299-
'Learn about middleware',
300-
'Learn about higher-order stores'
301-
)).subscribe();
52+
export default reducer;
30253
```
30354

304-
## See also
55+
For more complex scenarios we recommend reading our [documentation](https://redux-actions.js.org/).
30556

306-
Use redux-actions in combination with FSA-compliant libraries.
57+
# Documentation
30758

308-
- [redux-promise](https://github.com/acdlite/redux-promise) - Promise middleware
309-
- [redux-rx](https://github.com/acdlite/redux-rx) - Includes observable middleware.
59+
* [Introduction](/docs/introduction)
60+
* [API](/docs/api)
61+
* [Middleware](/docs/middleware)
62+
* [External Resources](/docs/ExternalResources.md)
63+
* [Change Log](/docs/ChangeLog.md)
64+
* [Contributors](/docs/Contributors.md)

SUMMARY.md

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Summary
2+
3+
* [Read Me](/README.md)
4+
* [1. Introduction](/docs/introduction/README.md)
5+
* [1.1 Motivation](docs/introduction/Motivation.md)
6+
* [1.2 Tutorial](/docs/introduction/Tutorial.md)
7+
* [2. API Reference](/docs/api/README.md)
8+
* [2.1 createAction(s)](/docs/api/createAction.md)
9+
* [2.2 handleAction(s)](/docs/api/handleAction.md)
10+
* [2.3 combineActions](/docs/api/combineActions.md)
11+
* [3. Middleware](/docs/middleware/README.md)
12+
* [4. External Resources](/docs/ExternalResources.md)
13+
* [5. Change Log](/docs/ChangeLog.md)
14+
* [6. Contributors](/docs/Contributors.md)

book.json

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"gitbook": ">= 3.0.0",
3+
"title": "Redux Actions",
4+
"plugins": ["edit-link", "prism", "-highlight", "github", "anchorjs"],
5+
"pluginsConfig": {
6+
"edit-link": {
7+
"base": "https://github.com/acdlite/redux-actions/tree/master",
8+
"label": "Edit This Page"
9+
},
10+
"github": {
11+
"url": "https://github.com/acdlite/redux-actions/"
12+
},
13+
"sharing": {
14+
"facebook": true,
15+
"twitter": true,
16+
"google": false,
17+
"weibo": false,
18+
"instapaper": false,
19+
"vk": false
20+
}
21+
}
22+
}

docs/ChangeLog.md

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Change Log
2+
3+
This project adheres to [Semantic Versioning](http://semver.org/).
4+
Every release, along with the migration instructions, is documented on the Github [Releases](https://github.com/acdlite/redux-actions/releases) page.

0 commit comments

Comments
 (0)