Building a Modern Web App with React and Redux

Building a Modern Web App with React and Redux

React is a JavaScript library for building user interfaces. It is fast, efficient, and easy to learn. Redux is a predictable state container for JavaScript apps. It helps you write applications that behave consistently, run in different environments, and are easy to test. React and Redux are often used together to build modern web applications.

In this tutorial, we will build a simple web app using React and Redux. We will create a todo list app that allows users to add, delete, and mark items as completed. We will also use Redux to manage the app's state.

Prerequisites:

To follow along with this tutorial, you should have a basic understanding of HTML, CSS, and JavaScript. You should also have Node.js and npm (Node Package Manager) installed on your machine.

Getting Started:

To get started, let's create a new React app using Create React App. Open your terminal and run the following command:

  1. npx create-react-app todo-list-app

This command will create a new React app in a directory named «todo-list-app». Once the installation is complete, navigate to the app's directory and start the app by running the following commands:

  1. cd todo-list-app
  2. npm start

This will start the app in your default web browser.

Creating the Todo Component:

Now that we have our app up and running, let's create a Todo component. This component will be responsible for rendering the todo list and managing its state. Create a new file named «Todo.js» in the «src» directory and add the following code:

  1. import React, { useState } from 'react';
  2.  
  3. function Todo() {
  4. const [todos, setTodos] = useState([]);
  5.  
  6. const handleAddTodo = () => {
  7. const newTodo = prompt('Enter new todo:');
  8. setTodos([...todos, newTodo]);
  9. };
  10.  
  11. const handleDeleteTodo = (index) => {
  12. const newTodos = [...todos];
  13. newTodos.splice(index, 1);
  14. setTodos(newTodos);
  15. };
  16.  
  17. const handleCompleteTodo = (index) => {
  18. const newTodos = [...todos];
  19. newTodos[index] = <del>{newTodos[index]}</del>;
  20. setTodos(newTodos);
  21. };
  22.  
  23. return (
  24. <div>
  25. <h1>Todo List</h1>
  26. <ul>
  27. {todos.map((todo, index) => (
  28. <li key={index}>
  29. <span onClick={() => handleCompleteTodo(index)}>{todo}</span>
  30. <button onClick={() => handleDeleteTodo(index)}>Delete</button>
  31. </li>
  32. ))}
  33. </ul>
  34. <button onClick={handleAddTodo}>Add Todo</button>
  35. </div>
  36. );
  37. }
  38.  
  39. export default Todo;

In this code, we import the useState hook from React, which allows us to manage the component's state. We then define a state variable called «todos» and a function to set its value. We also define three functions to handle adding, deleting, and completing todos. Finally, we render the todo list using a map function and the JSX syntax.

Integrating Redux:

Now that we have our Todo component, let's integrate Redux to manage the app's state. First, we need to install the necessary dependencies by running the following command:

  1. npm install redux react-redux

This will install the redux and react-redux packages.

Creating the Redux Store:

Next, let's create the Redux store. Create a new file named «store.js» in the «src» directory and add the following code:

  1. import { createStore } from 'redux';
  2.  
  3. const initialState = {
  4. todos: [],
  5. };
  6.  
  7. function rootReducer(state = initialState, action) {
  8. switch (action.type) {
  9. case 'ADD_TODO':
  10. return {
  11. todos: [...state.todos, action.payload],
  12. };
  13. case 'DELETE_TODO':
  14. return {
  15. todos: state.todos.filter((todo, index) => index !== action.payload),
  16. };
  17. case 'COMPLETE_TODO':
  18. return {
  19. todos: state.todos.map((todo, index) => {
  20. if (index === action.payload) {
  21. return <del>{todo}</del>;
  22. }
  23. return todo;
  24. }),
  25. };
  26. default:
  27. return state;
  28. }
  29. }
  30.  
  31. const store = createStore(rootReducer);
  32.  
  33. export default store;

In this code, we define the initial state of our app, which includes an empty array of todos. We also define a rootReducer function that takes the current state and an action as parameters and returns a new state based on the action.

The rootReducer function uses a switch statement to handle different actions. In this case, we handle the «ADD_TODO», «DELETE_TODO», and «COMPLETE_TODO» actions, which are dispatched by our Todo component.

Finally, we create the store by calling createStore and passing in our rootReducer function.

Connecting the App to Redux:

Now that we have our store set up, let's connect our app to Redux. Open the «index.js» file and add the following code:

  1. import React from 'react';
  2. import ReactDOM from 'react-dom';
  3. import { Provider } from 'react-redux';
  4. import store from './store';
  5. import Todo from './Todo';
  6.  
  7. ReactDOM.render(
  8. <Provider store={store}>
  9. <Todo />
  10. </Provider>,
  11. document.getElementById('root')
  12. );

In this code, we import the Provider component from the react-redux package, our store from the «store.js» file, and our Todo component from the «Todo.js» file. We then wrap our Todo component with the Provider component and pass in our store as a prop.

Updating the Todo Component:

Now that we have our app connected to Redux, let's update our Todo component to dispatch actions to the Redux store. Replace the contents of the «Todo.js» file with the following code:

  1. import React, { useState } from 'react';
  2. import { connect } from 'react-redux';
  3.  
  4. function Todo({ todos, dispatch }) {
  5. const [newTodo, setNewTodo] = useState('');
  6.  
  7. const handleAddTodo = () => {
  8. dispatch({
  9. type: 'ADD_TODO',
  10. payload: newTodo,
  11. });
  12. setNewTodo('');
  13. };
  14.  
  15. const handleDeleteTodo = (index) => {
  16. dispatch({
  17. type: 'DELETE_TODO',
  18. payload: index,
  19. });
  20. };
  21.  
  22. const handleCompleteTodo = (index) => {
  23. dispatch({
  24. type: 'COMPLETE_TODO',
  25. payload: index,
  26. });
  27. };
  28.  
  29. return (
  30. <div>
  31. <h1>Todo List</h1>
  32. <input
  33. type="text"
  34. value={newTodo}
  35. onChange={(e) => setNewTodo(e.target.value)}
  36. />
  37. <button onClick={handleAddTodo}>Add Todo</button>
  38. <ul>
  39. {todos.map((todo, index) => (
  40. <li key={index}>
  41. <span onClick={() => handleCompleteTodo(index)}>{todo}</span>
  42. <button onClick={() => handleDeleteTodo(index)}>Delete</button>
  43. </li>
  44. ))}
  45. </ul>
  46. </div>
  47. );
  48. }
  49.  
  50. const mapStateToProps = (state) => ({
  51. todos: state.todos,
  52. });
  53.  
  54. export default connect(mapStateToProps)(Todo);

In this code, we import the connect function from the react-redux package and pass in a mapStateToProps function to map the state from our Redux store to props for our component.

We also define three functions to handle adding, deleting, and completing todos. Instead of setting the state directly, these functions dispatch actions to the Redux store using the dispatch function provided by connect.

Finally, we wrap our Todo component with the connect function and pass in our mapStateToProps function.

Conclusion:

In this tutorial, we covered the basics of React and Redux and built a todo list app to demonstrate how they work together. We learned how to set up a React app using Create React App, create a component to manage the app's state, integrate Redux to manage the app's state, and connect our app to Redux using the connect function.

React and Redux are powerful tools for building modern web applications. With these frameworks, you can easily manage your app's state, make it more predictable and testable, and create complex user interfaces with ease. I hope this tutorial has been helpful in getting you started with React and Redux!

We use cookies to improve your browsing experience. By continuing to use this website, you consent to our use of cookies. Learn More