Redux
Table of Contents
About
Redux is a state manager.
Articles Related
Concept
The state inside a store is updated via a dispatch function that takes an action as argument and pass it to a reducer function. The reducer will calculate a new state passing it back to the store that will then:
- notify the subscribers
- and log the state change in a history table.
You can subscribe to a store in order to update the UI in response to state changes. For React, you'd use a view binding library (e.g. React Redux) that will take this work from you.
Installation
npm
npm install --save redux
npm install --save-dev redux-devtools
module
The module is available in the dist map : https://unpkg.com/[email protected]/dist/redux.min.js
Redux is then available as the REDUX globale variable
Concept
State
Single source of truth: The state of your whole application is stored in an object tree within a single store.
Debug:
- An handy way to follow the state is print it after each modification:
store.subscribe(() =>
console.log(store.getState())
)
- or the Chrome Redux Dev tool
Action
An action is an plain JavaScript object describing what happened with a mandatory type property. It will then be passed to the reducer function.
Example:
{
type: 'ADD_TODO',
text: 'Go to swimming pool'
}
Reducer
To specify how the actions transform the state tree, you write function called reducers.
A reducer takes an action as input and transforms the state into the next state.
The reducer function signature is
recuder(state, action) => nextState
where:
- the inputs are the actual state and the action dispatched.
- returns the next state.
Example:
function counter(state = 0, action) {
switch (action.type) {
case 'counter/INCREMENT':
return state + 1
case 'counter/DECREMENT':
return state - 1
default:
return state
}
}
A reducer creates its own context (scope). Therefore if you return an object, you can get it as: state.myReducer.myProperty.
You can have multiple reducer and then multiple context. You need to combine them in one with the CombineReducer function.
Example:
import { combineReducers } from 'redux'
import reducer1 from './reducer1'
import reducer2 from './reducer2'
// Just add a command list after inscription to add more reducer
const appReducer = combineReducers({
reducer1,
reducer2
})
export default appReducer
Store
A store is a container that holds the application's global state.
Its API is.
- createStore - Create a store with the reducers function
- subscribe - Update the UI
- dispatch - Send an action to the reducers
- getState - Get the state
Create
createStore(reducer, [initialState], [enhancer]) where:
- reducer - A reducing function.
- initialState - The initial state of the store.
- enhancer - Can be used to enhance the Redux store and add third-party libraries
let store = createStore(counter)
Subscribe
You can use subscribe() to update the UI in response to state changes. Normally you'd use a view binding library (e.g. React Redux) rather than subscribe() directly. However it can also be handy to persist the current state in the localStorage.
store.subscribe(() =>
console.log(store.getState())
)
Dispatch
The only way to mutate the internal state is to dispatch an action. The actions can be serialized, logged or stored and later replayed.
let action = { type: 'INCREMENT' }
store.dispatch(action)
GetState
store.subscribe(() =>
console.log(store.getState())
)
You can also see the state with the Browser extension
Example
- The action will have this properties
let action = {
type: "string" // INCREMENT or DECREMENT
}
- The reducer. It manipulate the state which is a single variable
function counter(state = 0, action) {
switch (action.type) {
case 'INCREMENT':
return state + 1
case 'DECREMENT':
return state - 1
default:
return state
}
};
- Creating a store with this reducer:
// If used in npm
// import {createStore} from 'redux'
let store = Redux.createStore(counter);
- Subscribe to the store to see the state
store.subscribe(() =>
console.log(store.getState())
)
- Perform an action (dispatch)
store.dispatch({ type: 'INCREMENT' })
// 1
store.dispatch({ type: 'INCREMENT' })
// 2
store.dispatch({ type: 'DECREMENT' })
// 1