React & Redux: A Visual Explanation
A visual explanation of React & Redux using the classic Todo App teaching exercise.
1. Overview of TodoApp
2. Break Into Components
<APP/>Stores our state, actions and renders all immediate children
<NEW_TODO_FORM/>Accepts text input and triggers "ADD" todo action
<FILTER/>Changes what items we want to display ("SHOW_ALL" or "SHOW_DONE")
Optional: Do not separate out
<FILTER/>into children components if logic is simple and instead keep within
<TODOLIST/>maps over filtered todo items and renders either
<TODO_ITEM/>renders the item and includes key action handlers such as mark as done, edit and delete
<EDIT_TODO_FORM/>renders the input as an input form with its own internal state. Note: we create this as a separate component as we require the feature to undo the edit and only update the state if "Update" button is clicked
3. Data Down Actions Up (DDAU)
- All/ Majority of application state is stored in a root parent component as a POJO. Also, action callbacks to change state are stored in the parent component
- Parent then passes down the relevant state and action callbacks to its children as
- Children components render the
propsand listen for UI events to trigger action callbacks
- Parent components then execute the callback functions to change state
- React then does the heavy-lifting to update the UI only for the state that has changed
4. Create our State (aka: the source of truth)
To filter data, create a helper function to render the items array based on what filter type is in the state - Do not duplicate state data.
Decide whether a
<EDIT_TODO_FORM>is rendered by creating an array of items that are marked as edit
5. Identify Action Handlers
6. Separate out Business Logic
Create a reducer which will be the black box handling our business logic. This is the basic principle of Redux:
prevState: the entire state that this reducer is responsible for handling
action.type: simple text instruction for our reducer to execute relevant function e.g.
action.payload: payload options our action.type and function requires to modify state
A new state is then created without mutating previous state. This business logic is easy to unit test and independent of framework. We then require the reducer to update the state of our components.