Creating a Reducer Function to handle each Action type and Update the Store Accordingly
Reducers are called reducers because they are used in the reduce() function, which is used to reduce an array of values to a single value. In Redux, reducers are used to reduce the current state of the store to a new state based on the action that is dispatched.
Creating a Reducer Function
To create a reducer function in Redux, you need to follow a few conventions. First, the function should take two arguments: the current state and an action. Second, the function should return a new state based on the action that is dispatched.
Here's an example of a simple reducer function:
const initialState = {
count: 0
};
function counterReducer(state = initialState, action) {
switch (action. Type) {
case 'INCREMENT':
return { count: state. Count + 1 };
case 'DECREMENT':
return { count: state. Count - 1 };
default:
return state;
}
}
In the above code snippet example, we're creating a reducer function called counterReducer
.
The function takes two arguments: the current state (which is initialized to an object with a count property set to 0) and an action.
The function returns a new state based on the action that is dispatched.
The reducer function uses a switch statement to handle different action types. In this example, we're handling two action types: INCREMENT and DECREMENT.
When the INCREMENT action is dispatched, the function returns a new state object with the count property incremented by 1. Similarly, when the DECREMENT action is dispatched, the function returns a new state object with the count property decremented by 1. If any other action is dispatched, the function simply returns the current state.
Combining Reducers
In larger applications, multiple reducers may handle different parts of the state. To combine these reducers into a single reducer function that can be passed to the store, Redux provides a combineReducers()
function.
Here's an example of how to use combineReducers()
to combine multiple reducers:
import { combineReducers } from 'redux';
const counterInitialState = {
count: 0
};
function counterReducer(state = counterInitialState, action) {
switch (action. Type) {
case 'INCREMENT':
return { count: state.count + 1 };
case 'DECREMENT':
return { count: state.count - 1 };
default:
return state;
}
}
const todosInitialState = {
items: []
};
function todosReducer(state = todosInitialState, action) {
switch (action. Type) {
case 'ADD_TODO':
return { items: [...state. Items, action.payload] };
case 'REMOVE_TODO':
return { items: state.items.filter(todo => todo.id !== action.payload) };
default:
return state;
}
}
const rootReducer = combineReducers({
counter: counterReducer,
todos: todosReducer
});
In this example, we're creating two reducers: counterReducer
and todosReducer
. Each reducer handles a different part of the state.
We're then using combineReducers()
to combine these reducers into a single reducer function called rootReducer. The resulting state object will have two properties: counter
and todos
, which correspond to the state handled by each reducer.
Using the Reducer in a React Component
Once you've created a reducer function and combined it with other reducers using combineReducers()
, you can use the resulting reducer function in a React component using the useReducer()
hook.
Here's an example of how to use the useReducer()
hook to manage state in a React component:
import React, { useReducer } from 'react';
function Counter() {
const [state, dispatch] = useReducer(counterReducer, { count: 0 });
function handleIncrement() {
dispatch({ type: 'INCREMENT' });
}
function handleDecrement() {
dispatch({ type: 'DECREMENT' });
}
return (
<div>
<h1>Count: {state. Count}</h1>
<button onClick={handleIncrement}>Increment</button>
<button onClick={handleDecrement}>Decrement</button>
</div>
);
}
In this example, we're using the useReducer()
hook to manage state in a component called Counter. We're passing the counterReducer
function as the first argument to useReducer()
, along with the initial state of the count (which is an object with a count property set to 0).
We're then defining two functions (handleIncrement() and handleDecrement())
that dispatch the INCREMENT
and DECREMENT
actions, respectively.
Finally, we're rendering the current count and two buttons that trigger the corresponding actions when clicked.
Creating a selector function to extract a specific piece of data from the store
In Redux, selectors are functions that are used to extract data from the state in a structured way. Selectors are especially useful when the state is complex or when you want to derive new data from the state.
In this section, we'll explain how to create and use selectors in a React application that uses Redux for state management.
Creating a Selector Function
To create a selector function, you can use the createSelector()
function from the reselect library. The createSelector()
function takes one or more input selectors and a transform function, and returns a memorized selector function.
Here's an example of how to create a selector function that extracts the current count from the state:
import { createSelector } from 'reselect';
const getCount = state => state.counter.count;
export const countSelector = createSelector(
[getCount],
count => count
);
In this example, we're using the createSelector()
function to create a memorized selector function called countSelector.
The selector function takes an input selector called getCount
, which simply extracts the count property from the counter slice of the state.
The transform function takes the count as input and returns it as output. The resulting countSelector
function can be used to extract the count from the state in an effective way.
Using the Selector Function in mapStateToProps()
Once you've created a selector function, you can use it in the mapStateToProps()
function to pass the data to the component as props.
Here's an example of how to use the countSelector function in mapStateToProps()
:
import { connect } from 'react-redux';
import { countSelector } from './selectors';
function Counter({ count, dispatch }) {
// ...
}
function mapStateToProps(state) {
return {
count: countSelector(state)
};
}
export default connect(mapStateToProps)(Counter);
In this example, we're using the connect()
function to connect a component called Counter
to the Redux store. We're importing the countSelector
function from a file called selectors.js
.
We're then defining a mapStateToProps()
function that maps the count property from the state to a prop called count in the component, using the countSelector
function to extract the count from the state. Finally, we're exporting the connected Counter component.
Conclusion
Selectors are a powerful tool in Redux that enable you to extract data from the state in a structured and performant way. By using the createSelector()
function from the reselect library, you can create memorized selector functions that extract new data from the state or extract specific pieces of data from the state. By using selectors in conjunction with the mapStateToProps()
function, you can pass the data to your React components as props and render the data in your UI.
Final Conclusion
we've discussed how Redux can be useful for managing complex state in a React application, and covered the following topics in previous sections:
- Installing the necessary packages (redux, react-redux)
- Creating a Redux store and initializing it with initial state
- Creating actions and action creators to update the store
- Creating reducers to handle the actions and update the store
- Connecting a React component to the Redux store using the useReducer() hook.
If you want to learn more about Redux and how to use it in a React application, here are some resources you might find helpful:
- Redux documentation:
- Getting Started with Redux course on Egghead:
- Redux Toolkit documentation:
- Reselect documentation: