Redux
Redux Basics
What is Redux?
Redux is a library for managing and updating application state, using events called “actions”. It serves as a centralized store for state that needs to be used across your entire application, with rules ensuring that the state can only be updated in a predictable fashion.
The patterns and tools provided by Redux make it easier to understand when, where, why, and how the state in your application is being updated, and how your application logic will behave when those changes occur.
When to use Redux
- You have large amounts of application state that are needed in many places in the app
- The app state is updated frequently over time
- The logic to update that state may be complex
- The app has a medium or large-sized codebase, and might be worked on by many people
Three Principles
Redux can be described in three fundamental principles:
- Single source of truth The state of your whole application is stored in an object tree within a single store
- State is read-only The only way to change the state is to emit an action, an object describing what happened
- Changes are amde with pure function To specify how the state tree is transformed by actions, you write pure reducers
Installation
To use Redux, need to first install redux and react-redux
1 | npm install redux react-redux |
Counter Example without Redux
We can convert a Counter component from using state to use Redux to store its state.
Counter component that doesn’t use Redux:
1 | import React, { useState } from "react"; |
Currently the count is a local state to the Counter component, we will move the count to Redux store and create actions and reducers to change this state.
Actions
An action is a plain JavaScript object that has a type
field. You can think of an action as an event that describes something that happened in the application. Actions usually contains payloads that is needed to update the state.
An action creator is a function that creates and returns an action object. We typically use these so we don’t have to write the action object by hand every time:
actions/index.js
1 | export const increase = step => ({ |
Here we define two action creators, increase and decrease.
Reducers
A reducer is a function that receives the current state and an action object, decides how to update the state if necessary, and returns the new state: (state, action) => newState.
Reducers must always follow some specific rules:
- They should only calculate the new state value based on the
state
andaction
arguments - They are not allowed to modify the existing
state
. Instead, they must make immutable updates, by copying the existingstate
and making changes to the copied values. - They must not do any asynchronous logic, calculate random values, or cause other “side effects”
reducers/counter.js
1 | const initialState = { |
Here the initialState is a javascript object that contains a number.
Redux expects that all state updates are done immutably. so you need to return a new object/array instead of modifying the existing state.
There are usually multiple Reducers, we can use combineReducers function to combine multiple reducers.
reducers/index.js
1 | import { combineReducers } from 'redux' |
Store
The current Redux application state lives in an object called the store.
The store is created by passing in a reducer.
index.js
1 | import { createStore } from 'redux' |
Optional: To use Redux with Redux DevTools Extension, you need to add an extract argument to createStore function.
1 | const store = createStore( |
Dispatch
The Redux store has a method called dispatch
. The only way to update the state is to call store.dispatch()
and pass in an action object. You can think of dispatching actions as “triggering an event” in the application.
One way to use dispatch is to use useDispatch
hook.
1 | const dispatch = useDispatch(); |
Counter Component
1 | import React, { useState } from "react"; |
React Redux provides a connect function for you to read values from the Redux store and dispatch actions. connect function accepts two parameters.
- mapStateToProps - function that transforms the current Redux store state into props of the component
- mapDispatchToProps - function or object. If it is a function. it should return an object full of functions that use
dispatch
to dispatch actions. If it is an object, it will contain functions that usedispatch
to dispatch actions.
Dataflow
Initial setup: A redux store is created with a root reducer function.
Update
- When user clicks a button, app code dispatch an action to the Redux store.
{type: 'INCREASE', step: 2}
- Reducer function runs with the previous state and current action. Return value as the new state.
- Store notify all parts of the UI that are subscribed that the store has been updated
- UI component re-render with the new state.
Counter Example with Redux
Here is the complete code for Counter example that uses Redux