Skip to content

Commit 5619b9e

Browse files
committed
Merge branch 'breaking-changes-1.0' into rewrite-docs
2 parents feb026d + 7418203 commit 5619b9e

13 files changed

+182
-153
lines changed

.eslintrc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
"node": true
77
},
88
"rules": {
9+
"valid-jsdoc": 2,
10+
911
"react/jsx-uses-react": 2,
1012
"react/jsx-uses-vars": 2,
1113
"react/react-in-jsx-scope": 2,

src/createStore.js

Lines changed: 81 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,35 @@
1-
/* @flow */
2-
/*eslint-disable */
3-
import type { State, Reducer, Action, IntermediateAction, Store } from './index';
4-
/*eslint-enable */
5-
61
import invariant from 'invariant';
72
import isPlainObject from './utils/isPlainObject';
83

9-
// Don't ever try to handle these action types in your code. They are private.
10-
// For any unknown actions, you must return the current state.
11-
// If the current state is undefined, you must return the initial state.
4+
/**
5+
* These are private action types reserved by Redux.
6+
* For any unknown actions, you must return the current state.
7+
* If the current state is undefined, you must return the initial state.
8+
* Do not reference these action types directly in your code.
9+
*/
1210
export var ActionTypes = {
1311
INIT: '@@redux/INIT'
1412
};
1513

16-
export default function createStore(
17-
reducer: Reducer,
18-
initialState: State
19-
): Store {
14+
/**
15+
* Creates a Redux store that holds the state tree.
16+
* The only way to change the data in the store is to call `dispatch()` on it.
17+
*
18+
* There should only be a single store in your app. To specify how different
19+
* parts of the state tree respond to actions, you may combine several reducers
20+
* into a single reducer function by using `combineReducers`.
21+
*
22+
* @param {Function} reducer A function that returns the next state tree, given
23+
* the current state tree and the action to handle.
24+
*
25+
* @param {any} initialState The initial state. You may optionally specify it
26+
* to hydrate the state from the server in universal apps, or to restore a
27+
* previously serialized user session.
28+
*
29+
* @returns {Store} A Redux store that lets you read the state, dispatch actions
30+
* and subscribe to changes.
31+
*/
32+
export default function createStore(reducer, initialState) {
2033
invariant(
2134
typeof reducer === 'function',
2235
'Expected the reducer to be a function.'
@@ -26,11 +39,24 @@ export default function createStore(
2639
var currentState = initialState;
2740
var listeners = [];
2841

42+
/**
43+
* Reads the state tree managed by the store.
44+
*
45+
* @returns {any} The current state tree of your application.
46+
*/
2947
function getState() {
3048
return currentState;
3149
}
3250

33-
function subscribe(listener: Function) {
51+
/**
52+
* Adds a change listener. It will be called any time an action is dispatched,
53+
* and some part of the state tree may potentially have changed. You may then
54+
* call `getState()` to read the current state tree inside the callback.
55+
*
56+
* @param {Function} listener A callback to be invoked on every dispatch.
57+
* @returns {Function} A function to remove this change listener.
58+
*/
59+
function subscribe(listener) {
3460
listeners.push(listener);
3561

3662
return function unsubscribe() {
@@ -39,7 +65,29 @@ export default function createStore(
3965
};
4066
}
4167

42-
function dispatch(action: Action) {
68+
/**
69+
* Dispatches an action. It is the only way to trigger a state change.
70+
*
71+
* The `reducer` function the store was created with will be called with the
72+
* current state tree and the and the given `action`. Its return value will
73+
* be considered the next state of the tree, and the change listeners will be
74+
* notified.
75+
*
76+
* The base implementation only supports plain object actions. If you want to
77+
* dispatch a promise, an observable, a thunk, or something else, you need to
78+
* wrap your store creating function into the corresponding middleware. For
79+
* example, see the documentation for the `redux-thunk` package. Even the
80+
* middleware will eventually dispatch plain object actions using this method.
81+
*
82+
* @param {Object} action A plain object representing “what changed”. It is
83+
* a good idea to keep actions serializable so you can record and replay user
84+
* sessions, or use the time travelling Redux developer tools.
85+
*
86+
* @returns {Object} For convenience, the same action object you dispatched.
87+
* Note that, if you use a custom middleware, it may wrap `dispatch()` to
88+
* return something else (for example, a Promise you can await).
89+
*/
90+
function dispatch(action) {
4391
invariant(
4492
isPlainObject(action),
4593
'Actions must be plain objects. Use custom middleware for async actions.'
@@ -50,11 +98,29 @@ export default function createStore(
5098
return action;
5199
}
52100

101+
/**
102+
* Returns the reducer currently used by the store to calculate the state.
103+
*
104+
* It is likely that you will only need this function if you implement a hot
105+
* reloading mechanism for Redux.
106+
*
107+
* @returns {Function} The reducer used by the current store.
108+
*/
53109
function getReducer() {
54110
return currentReducer;
55111
}
56112

57-
function replaceReducer(nextReducer: Reducer) {
113+
/**
114+
* Replaces the reducer currently used by the store to calculate the state.
115+
*
116+
* You might need this if your app implements code splitting and you want to
117+
* load some of the reducers dynamically. You might also need this if you
118+
* implement a hot reloading mechanism for Redux.
119+
*
120+
* @param {Function} nextReducer The reducer for the store to use instead.
121+
* @returns {void}
122+
*/
123+
function replaceReducer(nextReducer) {
58124
currentReducer = nextReducer;
59125
dispatch({ type: ActionTypes.INIT });
60126
}

src/index.js

Lines changed: 2 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,13 @@
1-
/* @flow */
2-
3-
export type State = any;
4-
export type Action = Object;
5-
export type IntermediateAction = any;
6-
export type Dispatch = (a: Action | IntermediateAction) => any;
7-
export type Reducer<S, A> = (state: S, action: A) => S;
8-
export type ActionCreator = (...args: any) => Action | IntermediateAction;
9-
10-
export type MiddlewareArgs = {
11-
dispatch: Dispatch;
12-
getState: () => State;
13-
};
14-
15-
export type Middleware = (args: MiddlewareArgs) =>
16-
(next: Dispatch) =>
17-
Dispatch;
18-
19-
export type Store = {
20-
dispatch: Dispatch;
21-
getState: () => State;
22-
getReducer: () => Reducer;
23-
replaceReducer: (nextReducer: Reducer) => void;
24-
subscribe: (listener: () => void) => () => void;
25-
};
26-
27-
export type CreateStore = (
28-
reducer: Reducer,
29-
initialState: State
30-
) => Store;
31-
32-
export type HigherOrderStore = (
33-
next: CreateStore
34-
) => CreateStore;
35-
361
import createStore from './createStore';
37-
import compose from './utils/compose';
382
import combineReducers from './utils/combineReducers';
393
import bindActionCreators from './utils/bindActionCreators';
404
import applyMiddleware from './utils/applyMiddleware';
41-
import composeMiddleware from './utils/composeMiddleware';
5+
import compose from './utils/compose';
426

437
export {
448
createStore,
45-
compose,
469
combineReducers,
4710
bindActionCreators,
4811
applyMiddleware,
49-
composeMiddleware
12+
compose
5013
};

src/utils/applyMiddleware.js

Lines changed: 16 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,30 @@
1-
/* @flow */
2-
/*eslint-disable */
3-
import type {
4-
Dispatch, Middleware, Reducer, State,
5-
Store, CreateStore, HigherOrderStore
6-
} from '../index';
7-
/*eslint-enable */
8-
91
import compose from './compose';
10-
import composeMiddleware from './composeMiddleware';
112

123
/**
13-
* Creates a higher-order store that applies middleware to a store's dispatch.
4+
* Creates a higher-order store that applies middleware to the dispatch method
5+
* of the Redux store. This is handy for a variety of tasks, such as expressing
6+
* asynchronous actions in a concise manner, or logging every action payload.
7+
*
8+
* See `redux-thunk` package as an example of the Redux middleware.
9+
*
1410
* Because middleware is potentially asynchronous, this should be the first
1511
* higher-order store in the composition chain.
16-
* @param {...Function} ...middlewares
17-
* @return {Function} A higher-order store
12+
*
13+
* @param {...Function} middlewares The middleware chain to be applied.
14+
* @returns {Function} A higher-order store.
1815
*/
19-
export default function applyMiddleware(
20-
...middlewares: Array<Middleware>
21-
): HigherOrderStore {
22-
return (next: CreateStore) => (reducer: Reducer, initialState: State) => {
16+
export default function applyMiddleware(...middlewares) {
17+
return (next) => (reducer, initialState) => {
2318
var store = next(reducer, initialState);
24-
var middleware = composeMiddleware(...middlewares);
25-
var composedDispatch = () => {};
26-
27-
function dispatch(action) {
28-
return composedDispatch(action);
29-
}
19+
var dispatch = store.dispatch;
20+
var chain = [];
3021

3122
var middlewareAPI = {
3223
getState: store.getState,
33-
dispatch
24+
dispatch: (action) => dispatch(action)
3425
};
35-
36-
composedDispatch = compose(
37-
middleware(middlewareAPI),
38-
store.dispatch
39-
);
26+
chain = middlewares.map(middleware => middleware(middlewareAPI));
27+
dispatch = compose(...chain, store.dispatch);
4028

4129
return {
4230
...store,

src/utils/bindActionCreators.js

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,21 @@
1-
/* @flow */
2-
/*eslint-disable */
3-
import type { Dispatch } from '../index';
4-
/*eslint-enable */
5-
61
import mapValues from '../utils/mapValues';
72

8-
export default function bindActionCreators(
9-
actionCreators: Object,
10-
dispatch: Dispatch
11-
): Object {
3+
/**
4+
* Turns an object whose values are action creators, into an object with the
5+
* same keys, but with every function wrapped into a `dispatch` call so they
6+
* may be invoked directly. This is just a convenience method, as you can call
7+
* `store.dispatch(MyActionCreators.doSomething())` yourself just fine.
8+
*
9+
* @param {Object} actionCreators An object whose values are action creator
10+
* functions. One handy way to obtain it is to use ES6 `import * as` syntax.
11+
*
12+
* @param {Function} dispatch The `dispatch` function available on your Redux
13+
* store.
14+
*
15+
* @returns {Object} The object mimicking the original object, but with every
16+
* action creator wrapped into the `dispatch` call.
17+
*/
18+
export default function bindActionCreators(actionCreators, dispatch) {
1219
return mapValues(actionCreators, actionCreator =>
1320
(...args) => dispatch(actionCreator(...args))
1421
);

src/utils/combineReducers.js

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,35 @@
1-
/* @flow */
2-
/*eslint-disable */
3-
import type { Action, State, Reducer } from '../index';
4-
/*eslint-enable */
5-
61
import mapValues from '../utils/mapValues';
72
import pick from '../utils/pick';
83
import invariant from 'invariant';
94
import { ActionTypes } from '../createStore';
105

11-
function getErrorMessage(key: String, action: Action): string {
6+
function getErrorMessage(key, action) {
127
var actionType = action && action.type;
13-
var actionName = actionType && `"${actionType}"` || 'an action';
8+
var actionName = actionType && `"${actionType.toString()}"` || 'an action';
149

1510
return (
1611
`Reducer "${key}" returned undefined handling ${actionName}. ` +
1712
`To ignore an action, you must explicitly return the previous state.`
1813
);
1914
}
2015

21-
export default function combineReducers(reducers: Object): Reducer {
16+
/**
17+
* Turns an object whose values are different reducer functions, into a single
18+
* reducer function. It will call every child reducer, and gather their results
19+
* into a single state object, whose keys correspond to the keys of the passed
20+
* reducer functions.
21+
*
22+
* @param {Object} reducers An object whose values correspond to different
23+
* reducer functions that need to be combined into one. One handy way to obtain
24+
* it is to use ES6 `import * as reducers` syntax. The reducers may never return
25+
* undefined for any action. Instead, they should return their initial state
26+
* if the state passed to them was undefined, and the current state for any
27+
* unrecognized action.
28+
*
29+
* @returns {Function} A reducer function that invokes every reducer inside the
30+
* passed object, and builds a state object with the same shape.
31+
*/
32+
export default function combineReducers(reducers) {
2233
var finalReducers = pick(reducers, (val) => typeof val === 'function');
2334

2435
Object.keys(finalReducers).forEach(key => {
@@ -43,7 +54,7 @@ export default function combineReducers(reducers: Object): Reducer {
4354
);
4455
});
4556

46-
return function composition(state: State = {}, action: Action): State {
57+
return function combination(state = {}, action) {
4758
return mapValues(finalReducers, (reducer, key) => {
4859
var newState = reducer(state[key], action);
4960
invariant(

src/utils/compose.js

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
/* @flow */
2-
31
/**
4-
* Composes functions from left to right
5-
* @param {...Function} funcs - Functions to compose
6-
* @return {Function}
2+
* Composes functions from left to right.
3+
*
4+
* @param {...Function} funcs - The functions to compose.
5+
* @returns {Function} A function that passes its only argument to the first of
6+
* the `funcs`, then pipes its return value to the second one, and so on, until
7+
* the last of the `funcs` is called, and its result is returned.
78
*/
8-
export default function compose(...funcs: Array<Function>): Function {
9+
export default function compose(...funcs) {
910
return funcs.reduceRight((composed, f) => f(composed));
1011
}

src/utils/composeMiddleware.js

Lines changed: 0 additions & 21 deletions
This file was deleted.

src/utils/isPlainObject.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
/* @flow */
2-
3-
export default function isPlainObject(obj: Object): boolean {
1+
/**
2+
* @param {any} obj The object to inspect.
3+
* @returns {boolean} True if the argument appears to be a plain object.
4+
*/
5+
export default function isPlainObject(obj) {
46
if (!obj) {
57
return false;
68
}

0 commit comments

Comments
 (0)