State is a plain object
To change something in state you must dispatch an action, an action is a plain JS object that describes what happened
To tie state and actions together we write a function called a reducer
We have multiple small reducer functions controlling each part of the state
Remember to return new state objects instead of mutating the previous state
Without middleware Redux store only supports synchronous data flow
You may enhance createStore with applyMiddleware, this lets you express async actions in a convenient way
Async middleware wraps the store’s dispatch method and allows you to dispatch something other than actions, e.g. functions or promises
Any middleware you use can then intercept anything you dispatch and can pass actions to the next middleware in the chain
When the last middleware in the chain dispatches an action it has to be a plain object, this is when the synchronous redux data flow takes place
The component should wrap round the component
Since one of the core tenets of redux is to never mutate state, you’ll often use Object.assign to create copies of objects with new or updated values
return Object.assign({}, state, { visibilityFilter: action.filter})
A less verbose way of doing the same thing using the spread operator:
return { ...state, visibilityFilter: action.filter }
It is a common convention that actions have a constant type that helps reducers identify them
Constants are a good way to do this
Instead of creating action objects inline it is a good idea to use functions that generate the objects
If an action changes then we only have to change the structure in one place
Without middleware dispatch only accepts plain objects so we would have to perform Ajax calls inside our components
This gets repetitive when different components want to make the same API calls
redux-thunk is the simplest solution
Reselect is a simple library for creating memoized compassable selector functions
This allows you to only recalculate values when that item in the state changes
It avoids unnecessary recalculations that can cause performance problems
It uses memoized selectors
Data encapsulated in an immutable.js is never mutated, a new copy is always returned
Immutable.js provides a rich set of immutable objects to encapsulate your data and an extensive set of methods to manipulate it
The first time the reducer is called, the value will be undefined, the reducer needs a default value
It needs to look at the previous state and the dispatched action and determine what kind of work needs to be done
It needs to create new objects and arrays with the updated data and return those
If no changes are needed it should return the existing state as-is
Most data can be divided into three categories:
The data should be structured in terms of domain data and app state, not the UI component tree