In Redux applications, selectors are functions that facilitate the retrieval of specific pieces of state from the Redux store. Selectors play a crucial role in decoupling components from the store's structure and improving performance by memoizing computed values. Let's explore two approaches to retrieving specific states using selectors.
Prerequisites:
Why Use Selectors?
- Encapsulation: Selectors encapsulate the logic for accessing and computing derived state, promoting code modularity and maintainability.
- Memoization: Selectors utilize memoization techniques to cache computed values, optimizing performance by preventing unnecessary recalculations.
- Reusability: Selectors can be reused across multiple components, ensuring consistency in data retrieval logic throughout your application.
- Testing: Selectors facilitate easier testing as they separate the concerns of state retrieval from component rendering, allowing for more focused unit tests.
Table of Content
Steps to Create the Project:
Step 1: Create a ReactJS application by using this command
npx create-react-app myapp
Step 2: Navigate to project directory
cd myapp
Step 3: Install the necessary packages/libraries in your project using the following commands.
npm install reselect
Project Structure:
The updated dependencies in package.json file will look like:
"dependencies": {
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"reselect": "^5.1.0",
"web-vitals": "^2.1.4"
}
Using a Simple Selector Function
In this approach, we directly access the users from the Redux store without any optimization. We retrieve the list of users and display them in a component. This method works fine for small-scale applications, but it may lead to performance issues as the application grows.
Example: This example uses the simple selector function to retrieve specific pieces of state using selectors.
// App.js
import React from 'react';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
// Define initial state
const initialState = {
users: [
{ id: 1, name: 'Rajveer', isActive: true },
{ id: 2, name: 'Malhotra', isActive: false },
{ id: 3, name: 'Veer', isActive: true },
// Add more users as needed
],
};
// Define reducer function
const reducer = (state = initialState, action) => {
// For simplicity, we're not
// handling any actions in this example
return state;
};
// Create Redux store
const store = createStore(reducer);
// Define UserList component
const UserList = ({ users }) => {
return (
<div>
<h2>All Users</h2>
<ul>
{users.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</div>
);
};
// Connect UserList component to Redux store
const ConnectedUserList = () => (
<Provider store={store}>
<UserListContainer />
</Provider>
);
// Map state to props for UserList component
const UserListContainer = () => {
const state = store.getState();
const users = state.users;
return <UserList users={users} />;
};
// App component
const App = () => {
return (
<div>
<h1>Basic Selector</h1>
<ConnectedUserList />
</div>
);
};
export default App;
Output:
Using Reselect Library
This approach utilizes Reselect library to create a memoized selector. It computes a derived data, such as active users, from the Redux store. Memoization optimizes performance by caching computed values, ensuring that expensive computations are only performed when necessary. This is especially beneficial for large-scale applications with complex state structures.
Example: This example uses the reselect library to retrieve specific pieces of state using selectors.
// App.js
import React from 'react';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import { createSelector } from 'reselect';
const initialState = {
elements: [10, 20, 30, 40, 50],
};
// Define reducer function
const reducer = (state = initialState, action) => {
// For simplicity, we're not handling
// any actions in this example
return state;
};
// Create Redux store
const store = createStore(reducer);
// Define selector functions
const getElements = (state) => state.elements;
const selectEvenElements = createSelector(
getElements,
(elements) => elements.filter(
(element) => element % 2 === 0)
);
// Define EvenElementList component
const EvenElementList = ({ evenElements }) => {
return (
<div>
<h2>Even Elements</h2>
<ul>
{evenElements.map((element, index) => (
<li key={index}>{element}</li>
))}
</ul>
</div>
);
};
// Connect EvenElementList component to Redux store
const ConnectedEvenElementList = () => (
<Provider store={store}>
<EvenElementListContainer />
</Provider>
);
// Map state to props for EvenElementList component
const EvenElementListContainer = () => {
const state = store.getState();
const evenElements = selectEvenElements(state);
return <EvenElementList evenElements={evenElements} />;
};
// App component
const App = () => {
return (
<div>
<h1>Using Reselect</h1>
<ConnectedEvenElementList />
</div>
);
};
export default App;
Step to Run Application: Run the application using the following command from the root directory of the project
npm start
Output: Your project will be shown in the URL http://localhost:3000/