Store holds the state tree of the application. It is an object that contains a few methods: getState(), dispatch(), subscribe(), replaceReducer().
Store is considered the single source of truth for the entire application.
Store is read-only you can only dispatch actions on it.
API
createStore()
/** * Used to intialize `store` object. * * @param {Function} reducer Reducer function used to change app state. * @param {?Object} state Intial state passed to the reducer function. * @param {?Function} enhancer Middleware functions combination. * @return {Object} */createStore(reducer, ?state, ?enhancer);
store.dispatch()
/** * Used to dispatch actions in order to change store state. * * @param {Object} actionObject. * @return {Object} New state object. */store.dispatch(actionObject);
store.subscribe()
/** * Calls all callbacks in subscribed components each time the store changes. * Updates UI on state changes . * * @param {Function} listener Callback function called on state changes. * @return {Void} */store.subscribe(listener);
store.getState()
/** * Used to return store state. * * @return {Object} State object. */store.getState()
store.replaceReducer()
/** * Used to implement hot reloading and code splitting. Most likely you won't use it. * * @param {Function} nextReducer Reducer function injected. * @return {Viod}. */store.replaceReducer(nextReducer);
Action
Notes
Action is a plain object that represents an intention to change the state.
Action is the only way to get data into the store.
Action must have a type property that indicates the type of action being performed.
Action types can be defined as constants and imported from another module.
Action should be constructed based on Flux standard action (FSA) for consistency.
Action MUST be a plain JavaScript object.
Action MUST have a type property.
Action MAY have an error property.
Action MAY have a payload property.
Action MAY have a meta property.
Action MUST NOT include properties other than type, payload, error, and meta.
Action creator: function that returns action object.
Reducer
Notes
Reducer is a function which takes the current state, and returns a new state depending on the action it was given.
Reducer contains all business logic and manipulates the state in the store.
Reducer analyzes action type and perform changes on the state copy according to the actions.
Reducer must be pure function.
API
combineReducer()
/** * Used to combine all smaller reducer into a root reducer. * * @param {Object} slices Object whose keys matches the shape of the state object and values are passed reducers. * @return {Viod}. */combineReducer(slices);
Middleware
Syntax
store=>next=>action=>{// Magic// ?next(action)}
Notes
Middleware is simply a decorator for dispatch() to allow you to take different kinds of actions, and to perform different tasks when receiving actions.
Middleware sequences are executed from left to right. The last function that is executed is actually the dispatch() function itself.
Middleware contains all our side-effects (interaction with the outside world):
Server Requests (API Calls)
ID Generation
Logging
...etc
API
applyMiddleware()
/** * Creates a store enhancer that applies middleware to the dispatch method * of the Redux store. * * @param {...Function} args Middlewares functions. * @return {Function} A store enhancer applying the middleware. */applyMiddleware(...args);
Redux Workflow
Create root reducer, which describes the app's state and all its logic.
Create Redux Store using createStore(reducer) and pass the main reducer to it.
Call store.dispatch(actionCreator()) to make changes in Store
Use store.subscribe(callback) to invoke all callback functions that need to update on any store change.
The connect() function returns a higher order component, i.e. a component that expects a component as an argument.
The higher order component created by the connect() function renders the smart component passing the data from the store into its props.
connect() function is the glue between smart component and Redux store.
Syntax
/** * Connects the passed component to Redux store. * * @param {Function|null} [mapStateToProps] Describes how returned state from the Store will be mapped to the props passed to the Component. * @param {Function|Object|null} [mapDispatchToProps] Maps action creator functions to Component props. * * @return {Function} Returns new connected Component Class * */connect(mapStateToProps,mapDispatchToProps)(Component);
mapStateToProps()
Notes
mapStateToProps is called on any Redux Store update. When Component receives new props - mapStateToProps will be additionally re-invoked.
Syntax
/** * Connects the passed component to Redux store. * * @param {Object} state Redux state from the Store. * @param {Object} ownProps `props` passed to the Component by Parent. * * @return {Object} Plain object that will be merged into the Component's props. * @return {null} Component will not be subscribed to the Redux Store. * */mapStateToProps(state,ownProps);
mapDispatchToProps
Notes
Maps action creator functions to component props.
mapDispatchToProps => <Object>, each action creator inside will be wrapped into a dispatch() call and this object will be merged into component's props.
Don't use store.getState() in render(), try to save store data in component state instead.
Don't mutate received state in reducer, otherwise Redux will not update the components!.
Don't use Redux store for storing "localized" data when you're dealing with state that doesn't affect other components, component state is a solid choice for this case.
Do keep the reducers & action creators as a pure functions.
Do add extra data to the payload (in the reducer or middleware).
Do create single file and use constants for action names to avoid mistakes in spelling actions.
Do keep payload data as small as possible. Have your resources only send the necessary data!.
Do name a reducer function after the state slice it manages.
Do use selectors , always, inside mapStateToProps instead of writing the computation logic diretly to it.
Do use Reselect for selectors that need to be memoized.
Do use redux-actions to reduce boilerplate and enforce FSA-compliant actions.
Do name action like: <VERB>_<NOUN>.
Do name action creator: <verb><Noun>.
Do name selector: get<Noun>.
Do build your reducers using redux-actionshandleActions().
Do structure your Redux files with the Ducks pattern in a single folder (often called flux/, ducks/, or stores/).