In Redux, there are some techniques used to retrieve specific pieces of state from the Redux store.
In this article, we will create a to-do list application using Redux and React, and we use the Reselect library for optimized state selection. This app provides basic functionalities such as adding new to-dos and displaying a list of existing to-dos. This serves a practical knowledge to retrieve a specific piece of state from the Redux store.
Approach to retrieve state
- Project Setup: The project follows a file structure for a React application created with create-react-app. This includes separate files and folders for components, Redux store, and React configuration.
- Create App: Create a new React project using Create React App and install Redux and React Redux to manage the application state.
- State Management: Code of Reducers, actions, and selectors are organized in one file.
- Component: Create a functional component ( App.js ) main component and connect it to the Redux store.
- Styling: Create a CSS file ( App.css ) for styling the input field, buttons, and to-do list.
Steps to Create Application
Step 1: Create React Application named redux-selector-app and navigate to it using this command.
npx create-react-app redux-selector-app
cd redux-selector-app
Step 2: Install required packages and dependencies.
npm install react react-redux redux reselect
Updated dependencies
Updated dependencies will look like in package.json file.
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-redux": "^9.1.1",
"redux": "^5.0.1",
"reselect": "^5.1.0",
},
Project Structure:
Example: The following codes implements the above approach.
/* App.css */
#app {
text-align: center;
display: flex;
margin-top: 20px;
justify-content: center;
}
button {
padding: 10px 20px;
background-color: rgba(220, 224, 219, 0.87);
border: 1px solid black;
cursor: pointer;
}
button:hover {
background-color: rgba(4, 163, 4, 0.637);
}
input {
padding: 10px 20px;
}
li {
list-style: none;
}
// store.js
import { createStore, combineReducers } from 'redux';
import { createSelector } from 'reselect';
// Reducers
const todosReducer = (state = { todos: [] }, action) => {
switch (action.type) {
case 'ADD_TODO':
return {
...state,
todos: [...state.todos, action.payload],
};
default:
return state;
}
};
// Actions
export const addTodo = todo => ({
type: 'ADD_TODO',
payload: todo,
});
// Selectors
const getTodosState = state => state.todos;
export const getTodos = createSelector(
[getTodosState],
todosState => todosState.todos
);
// Combine Reducers
const rootReducer = combineReducers({
todos: todosReducer,
});
// Create Redux Store
const store = createStore(rootReducer);
export default store;
// index.js
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import { Provider } from "react-redux";
import store from "./store";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<Provider store={ store } >
<App />
< /Provider>
);
// App.js
import React, { useState } from "react";
import { connect } from "react-redux";
import { addTodo, getTodos } from "./store";
import "./App.css";
const App = ({ todos, addTodo }) => {
const [newTodo, setNewTodo] = useState("");
const handleAddTodo = () => {
if (newTodo.trim() !== "") {
addTodo({
id: Date.now(),
text: newTodo,
completed: false,
});
setNewTodo("");
}
};
return (
<div id="app">
<div>
<h1>
<img
src="https://media.geeksforgeeks.org/gfg-gg-logo.svg"
alt="gfg_logo"
/>
Todo List{" "}
</h1>
<input
type="text"
value={newTodo}
onChange={(e) => setNewTodo(e.target.value)}
placeholder="Enter a new todo..."
/>
<button onClick={handleAddTodo}>Add Todo</button>
<ul>
{todos.map((todo) => (
<li key={todo.id}>{todo.text}</li>
))}
</ul>
</div>
</div>
);
};
const mapStateToProps = (state) => ({
todos: getTodos(state),
});
const mapDispatchToProps = {
addTodo,
};
export default connect(mapStateToProps, mapDispatchToProps)(App);
Output: