Concepts and Knowledge
The Redux store is a fundamental concept in Redux, and it serves as a centralized place to store and manage the state of your application. It helps you manage the data and the application's behavior in a predictable and organized manner. This has several advantages which include better communication between components, a single source of truth for the whole application, it's easier to debug since the data flows in one single direction and redux offers a Chrome extension that can be used to visualize states in the browser during the development of the application.
Here's an explanation of what a Redux store is and how it works:
State Container: The Redux store is essentially a TypeScript object that holds the entire state of your application. This state can include data like user profiles, application settings, and any other information that needs to be shared across different parts of your application.
Single Source of Truth: In Redux, there is a core principle known as "single source of truth." This means that all the application's state is stored in a single object (the store), making it easier to maintain and manage the state consistently throughout your application.
Immutability: The state stored in the Redux store is immutable. This means that you cannot directly modify the state. Instead, when you want to make changes to the state, you create a new state object with the desired changes. This helps ensure the predictability of state changes.
Actions and Reducers: To update the state in the Redux store, you dispatch actions. Actions are plain JavaScript objects that describe the type of action to be performed and may include additional data. Reducers are functions that specify how the state should change in response to actions. They take the current state and the action as input and return a new state.
Store Methods: The Redux store provides a set of methods for interacting with the state, including getSelector
to access the current state, dispatch
to dispatch actions.
Redux Toolkit is an official set of tools and utilities provided by the Redux team to simplify and streamline the process of working with Redux in a React application. It's designed to help you write Redux code more efficiently, reduce boilerplate, and make it easier to manage and maintain your Redux store and associated code.
Redux Toolkit includes several key features and benefits:
Simplified Redux Configuration: Redux Toolkit simplifies the setup of a Redux store by providing the configureStore
function. This function combines the following Redux setup steps into a single call:
- Creating a Redux store
- Configuring middleware, including the popular
redux-thunk
middleware for handling asynchronous actions - Setting up development tools, such as Redux DevTools, for debugging
- Optimizing performance by enabling the Immer library for immutable state updates
Reducer and Action Creation: Redux Toolkit offers functions like createSlice
and createAsyncThunk
that make it easier to define reducers and create actions. createSlice
generates action creators and reducers with less boilerplate code, and createAsyncThunk
simplifies handling asynchronous actions.
Immutability with Immer: Redux Toolkit promotes immutability and automatically uses the Immer library under the hood. This makes it much easier to work with immutable state updates in reducers, as it allows you to write code that looks like you're modifying the state directly.
Reduced Boilerplate: By providing utilities like createSlice
, Redux Toolkit reduces the amount of boilerplate code you need to write for Redux. You can define actions, reducers, and initial state in a more concise and readable manner.
Better Development Experience: Redux Toolkit helps improve the development experience by enabling Redux DevTools and providing better defaults for debugging and performance optimizations.
Initial State
The initial state represents the application's state before any actions have been dispatched. It's a plain TypeScript object that defines the initial values of different parts of your application's state. It's provided when creating the Redux store using createStore
or, in the case of Redux Toolkit, when defining a slice.
Action
An action in Redux is a plain TypeScript object that describes an event or an intention to change the state of the application. Actions have a mandatory type
property, which is a string that describes the action's type. It typically follows a naming convention like "ACTION_TYPE"
in uppercase. Actions may also include optional data in their payload
property, providing additional information required for the state change. Actions are dispatched using the dispatch
function and serve as the input for reducers to determine how the state should be updated.
In Redux Toolkit, you often use the createSlice
function to define reducers and action creators together in a more compact way. createSlice
generates action creators for each reducer case, eliminating the need to write action types and action creator functions separately. The generated action creators are automatically named based on the reducer's case names, which reduces naming inconsistencies and errors. These action types are stored as properties so you don't need to define and manage action type constants separately.
Reducer
A reducer is a pure function in Redux that specifies how the application's state should change in response to dispatched actions. It takes the current state and an action as input and returns a new state. Reducers are responsible for immutably updating the state, meaning they create a new state object with the desired changes instead of modifying the existing state. The state changes made by reducers are predictable and based on the action type.
Slices
In Redux Toolkit, a "slice" is a concept that encompasses a collection of related Redux functionality: it includes a reducer, action creators, and the initial state. Slices are used to organize and encapsulate the state management logic for a specific part of your application's state. They make it easier to modularize your Redux store and simplify the process of defining reducers and actions.
To create a slice, you use the createSlice
function provided by Redux Toolkit. It takes an object as an argument with the following properties:
name
: A string that represents the name of the slice. It's used to generate action types.initialState
: The initial state for this slice.reducers
: An object that defines reducer functions. Each key-value pair in the reducers
object represents a specific action type and the reducer function that handles it.
Here's how to access the reducer and action creators:
// counterSlice.ts
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
interface CounterState {
value: number;
}
const initialState: CounterState = {
value: 0,
};
const counterSlice = createSlice({
name: 'counter',
initialState,
reducers: {
increment: (state) => {
state.value += 1;
},
decrement: (state) => {
state.value -= 1;
},
},
});
export const { increment, decrement } = counterSlice.actions;
export default counterSlice.reducer;
Accessing the Reducer and Action Creators: After creating the slice, you can access the generated reducer and action creators through the counterSlice
object:
reducer
: The reducer function that manages the state for this slice.- Action creators: Action creators are automatically generated for each reducer function defined in the
reducers
object. They can be accessed as properties of the slice.
Thunks
A Thunk refers to a special kind of function that allows you to perform asynchronous actions in Redux. Thunks are often used to handle side effects such as making API requests, performing asynchronous operations, and dispatching multiple actions in response to the result of those operations.
Here's a breakdown of what a thunk is and how it is used with Redux Toolkit:
Asynchronous Actions: Redux's standard action dispatching mechanism is synchronous. However, in real-world applications, you often need to perform asynchronous operations, like fetching data from an API. Thunks allow you to handle these asynchronous actions within the Redux workflow.
Middleware: Thunks are typically used with Redux middleware, such as redux-thunk
or built-in middleware provided by Redux Toolkit. Middleware allows you to intercept dispatched actions and add custom behavior, like handling asynchronous operations, before they reach the reducers.
Definition: A thunk is a function that, when dispatched, can perform side effects and dispatch regular Redux actions. This function receives two arguments: dispatch
and getState
, which can be used to dispatch actions and access the current state of the Redux store.
Redux Toolkit's createAsyncThunk
: Redux Toolkit provides a utility called createAsyncThunk
that simplifies the process of creating thunks for handling asynchronous actions. It generates a set of actions and reducers for handling common asynchronous operations like data fetching. You specify the async operation and how it should affect your Redux state, and Redux Toolkit does the heavy lifting for you.