Actions, Reducers, and Store Explained
Key Concepts
- Actions
- Reducers
- Store
- Dispatch
- State Management
- Pure Functions
- Immutable State
- Middleware
- Combine Reducers
- Initial State
- State Immutability
- Action Creators
- Redux Flow
- Redux DevTools
Actions
Actions are payloads of information that send data from your application to your store. They are the only source of information for the store. Actions are plain JavaScript objects that must have a type property to indicate the type of action being performed.
Example:
const addTodo = (text) => { return { type: 'ADD_TODO', text }; };
Reducers
Reducers specify how the application's state changes in response to actions sent to the store. Reducers are pure functions that take the previous state and an action, and return the next state. It's important to keep reducers pure so that the state remains predictable.
Example:
const todos = (state = [], action) => { switch (action.type) { case 'ADD_TODO': return [ ...state, { text: action.text, completed: false } ]; default: return state; } };
Store
The store holds the whole state tree of your application. The only way to change the state inside it is to dispatch an action on it. The store is not a class but an object with a few methods, including getState(), dispatch(action), and subscribe(listener).
Example:
import { createStore } from 'redux'; const store = createStore(todos);
Dispatch
Dispatch is the method used to dispatch actions to the store. When an action is dispatched, the store runs the reducer function to update the state.
Example:
store.dispatch(addTodo('Learn Redux'));
State Management
State management in Redux involves managing the state of your application in a predictable way. The state is stored in a single object tree within a single store, making it easier to manage and debug.
Pure Functions
Reducers in Redux are required to be pure functions. A pure function is a function that, given the same input, will always return the same output and does not cause any side effects.
Immutable State
In Redux, the state is immutable. This means that the state cannot be changed directly. Instead, new state objects are returned from reducers. This ensures that the state remains predictable and easier to track changes.
Middleware
Middleware in Redux provides a third-party extension point between dispatching an action and the moment it reaches the reducer. It is useful for logging, crash reporting, performing asynchronous tasks, etc.
Example:
import { applyMiddleware, createStore } from 'redux'; import logger from 'redux-logger'; const store = createStore(todos, applyMiddleware(logger));
Combine Reducers
Combine reducers is a utility function to combine multiple reducers into a single reducer function. This is useful when your application state is managed by multiple reducers.
Example:
import { combineReducers } from 'redux'; const rootReducer = combineReducers({ todos, visibilityFilter });
Initial State
The initial state is the state of the application when it first starts. Reducers can define an initial state as a default parameter.
Example:
const todos = (state = [], action) => { // Reducer logic here };
State Immutability
State immutability ensures that the state cannot be changed directly. This is achieved by returning new state objects from reducers instead of mutating the existing state.
Action Creators
Action creators are functions that create actions. They return an action object that can be dispatched to the store.
Example:
const addTodo = (text) => { return { type: 'ADD_TODO', text }; };
Redux Flow
The Redux flow is a unidirectional data flow. It starts with dispatching an action, which is then handled by a reducer to update the state, and finally, the updated state is passed to the view.
Redux DevTools
Redux DevTools is a development tool that allows you to inspect the state and action history of your Redux store. It helps in debugging and understanding the flow of actions and state changes.
Example:
import { createStore } from 'redux'; import { composeWithDevTools } from 'redux-devtools-extension'; const store = createStore(todos, composeWithDevTools());
Analogies
Think of Redux as a kitchen where the store is the pantry, actions are the ingredients, and reducers are the recipes. When you want to cook a dish (update the state), you follow a recipe (reducer) using the ingredients (actions) from the pantry (store).
Another analogy is a library where the store is the catalog, actions are the requests for books, and reducers are the librarians who update the catalog based on the requests.