FOR DEVELOPERS

How to Build React Apps Using Redux as an Expert

How To Build React Apps Using Redux As An Expert

Are you planning to work on a React application but aren’t sure how to get started? Or maybe you're an experienced developer in React and want to learn how to use Redux for your next project. Whatever your position, most React developers recommend using Redux for app development. In this article, we’ll look at what Redux in React is, its advantages, and why it is recommended for app development.

What is Redux in React?

Back in 2015, Dan Abramov and Andrew Clark introduced Redux, an open-source JavaScript library that is mostly used by React developers to build a smooth user interface (UI).

React Redux is an official React library for Redux. With it, React components can read data from the Redux store and perform an action accordingly to update data. Redux uses a unidirectional data flow model to help the app to scale.

React Redux monitors the Redux store, checks if the component data has changed, and re-renders the same.

The main objective of the Redux library is to solve the state management problem that occurs in JavaScript apps. It imposes app restrictions about how and when state updates take place.

Principles of Redux.webp

These restrictions are put into action by Redux's ‘three principles of the state’. They are as follows:

Single source of truth

The Redux store holds the state of all your applications. This state gets represented as a visual tree with a single branch. The store also provides a method for reading the current state of components and the monitoring tracker within your app.

State is read-only

You can change the state by sending data as a plain text or object called an action. Here, actions are similar to you requesting the state by saying, "I have some data and I would like to perform insert/update/delete.”

Changes are written with pure functions

To change the state of your app, you have to write a function that will fetch the previous state of the app along with the action and return the object with a new state. This function is known as a reducer. It's a pure form of function as it returns the same output according to the given input.

The above-mentioned last principle is important in terms of Redux as it is here that all the magic of Redux happens. The Redux team offers a toolkit to make coding efficient and easy. It is used for Redux store setup and provides helpful add-ons for simplifying application code.

Why use Redux?

When using Redux and React together, the application state doesn't need to be lifted. It will also help you track which action is causing the change in the application.

The following are some beneficial features of using Redux for state management.

Maintainable

Redux focuses on how the application code should get organized. It makes it easy for developers to understand the application structure and also makes it easier to maintain.

Easy to debug

Application debugging is easy in Redux. You can log the actions and their state. It helps developers understand code errors, network errors, and other bugs that show up during production time.

Easy to test

Testing the Redux app is simple since all the components change their state with pure functions.

Getting started with Redux

Here, we will create a Todo list app. Before getting started with commands and codes, you need to create the folder structure for this project inside the src folder as shown below.

Redux(Directory)
   		Reducer.js (for creating actions and reducer)
   		Store.js
components(Directory)
   		Todos.js
   		TodoItem.js
    		DisplayTodos.js
css(Directory)
   		main.css

Step 1: Environmental setup

Open the terminal and go to the folder where you want to create your new React project. Enter the commands below to create an app.

npx create-React-app todo-list
cd todo-list

Step 2: Add Redux in React

The following command will install Redux and other essential libraries for this project.

npm install React-Redux @Reduxjs/toolkit framer-motion React-icons

Step 3: Create the app

Now that we’re done installing the libraries we need, it’s time to begin coding.

We begin by adding one input field and one button for our program in Todos.js file.

#Todos.js
import React, { useState } from "React";

const Todos = (props) => { const [todo, setTodo] = useState("");

const handleChange = (e) => { setTodo(e.target.value); };

return ( <div className="addTodos"> <input type="text" onChange={(e) => handleChange(e)} className="todo-input-field" value={todo} />

  &lt;button className=&quot;add-btn&quot;&gt;
    Add to list
  &lt;/button&gt;
  &lt;br /&gt;
&lt;/div&gt;

); }; export default Todos;

Next, we create a reducer, which is the pure function that will change the application state.

import { createSlice } from "@Reduxjs/toolkit";

const initialState = [];

const addTodoReducer = createSlice({ name: "todos",

initialState,

reducers: { //here we will write our reducer code //Adding todos addTodos: (state, action) => { state.push(action.payload); return state; },

},

});

export const { addTodos } = addTodoReducer.actions; export const reducer = addTodoReducer.reducer;

We need to use the default createSlice() function. It accepts one object with three parameters, slice function name, function initial State, and the entire reducer logic packed with reducers{} object.

Now, we create a store, which is a state container that contains the application state.

import { configureStore } from "@Reduxjs/toolkit";
import { reducer } from "./reducer";

const store = configureStore({ reducer: reducer, });

export default store;

We have used the configureStore() function that contains a reducer object. Note that whenever you create a store in the Redux application, you have to specify the reducer.

Step 4: Connect Redux store to React app

It's time to connect the store to the React application. To do so, open the index.js file under the src folder. Then, import Provider from React-Redux library and store from store.js.

import { Provider } from "React-Redux";
import store from "./Redux/store";

Use the Provider to wrap the component and pass store as argument in the Provider as given below.

ReactDOM.render(
  <React.StrictMode>
//similar to this
    <Provider store={store}>
      <App />
    </Provider>

</React.StrictMode>, document.getElementById("root") );

Congratulations! The Redux store and React app are now connected.

Step 5: Connect React components with Redux

It’s now time to connect React components with Redux. Open the Todos.js file and import store.js file along with its functionalities.

To connect these components with Redux, we will use the default function connect() from the React-Redux library.

Open the Todos.js file and import the default connect() function from the React-Redux library.

import { connect } from "React-Redux";

Now, change the export default Todos line with the following:

export default connect(null,null)(Todos);

This way, we connect the method to components with Redux.

To use and manipulate state from Redux, we need to pass the mapStateToProps method in the connect method.

To pass this as an argument, we have to define and add mapDispatchToProps() to the connect method. We can then use actions and other functions from our reducer.

Let's create both of the above functions in the Todos.js file.

//A state argument will get passed to this method, and it will return state

const mapStateToProps = (state) => { return { todos: state, }; };

//This function takes dispatch as an argument and dispatches an action to the reducer.

const mapDispatchToProps = (dispatch) => { return { addTodo: (obj) => dispatch(addTodos(obj)), }; };

We now add both methods in the connect() function as an argument like this:

export default connect(mapStateToProps, mapDispatchToProps)(Todos);

It's time to connect the input and button with state and methods. Our Todos.js file will look like this.

import React, { useState } from "React";
import { connect } from "React-Redux";
import { addTodos } from "../Redux/reducer";

const mapStateToProps = (state) => { return { todos: state, }; };

const mapDispatchToProps = (dispatch) => { return { addTodo: (obj) => dispatch(addTodos(obj)), }; };

const Todos = (props) => {

console.log("props",props);

const [todo, setTodo] = useState("");

const add = () =&gt; {
if (todo === &quot;&quot;) {
  alert(&quot;Input cannot be Empty&quot;);
} else {
  props.addTodo({
    id: Math.floor(Math.random() * 1000),
    item: todo,
    completed: false,
  });
  setTodo(&quot;&quot;);
}

};

const handleChange = (e) => { setTodo(e.target.value); };

return ( <div className="addTodos"> <input type="text" onChange={(e) => handleChange(e)} className="todo-input" value={todo} />

  &lt;button className=&quot;add-btn&quot;  onClick={() =&gt; add()}&gt;
    Add
  &lt;/button&gt;
  &lt;br /&gt;
  
  &lt;ul&gt;
    {props.todos.length &gt; 0 &amp;&amp;
      props.todos.map((item) =&gt; {
        return &lt;li key={item.id}&gt;{item.item}&lt;/li&gt;;
      })}
  &lt;/ul&gt;
    
&lt;/div&gt;

); };

//we can use the default connect method to connect this component with Redux store export default connect(mapStateToProps, mapDispatchToProps)(Todos);

Next, we add all the desired operations in the reducer. To do this, update the reducer.js file with the following code:

import { createSlice } from "@Reduxjs/toolkit";

const initialState = [];

const addTodoReducer = createSlice({ name: "todos", initialState, reducers: { //this is our reducer //add todos addTodos: (state, action) => { state.push(action.payload); return state; }, //remove todos removeTodos: (state, action) => { return state.filter((item) => item.id !== action.payload); }, //update todos updateTodos: (state, action) => { return state.map((todo) => { if (todo.id === action.payload.id) { return { ...todo, item: action.payload.item, }; } return todo; }); }, //completed completeTodos: (state, action) => { return state.map((todo) => { if (todo.id === action.payload) { return { ...todo, completed: true, }; } return todo; }); }, }, });

export const { addTodos, removeTodos, updateTodos, completeTodos, } = addTodoReducer.actions; export const reducer = addTodoReducer.reducer;

We need to display the todos component on the screen. Open the TodoItem.js file and write the code below in it:

import React, { useRef } from "React";
import { AiFillEdit } from "React-icons/ai";
import { IoCheckmarkDoneSharp, IoClose } from "React-icons/io5";

const TodoItem = (props) => {

const { item, updateTodo, removeTodo, completeTodo } = props;

const inputRef = useRef(true);

const changeFocus = () => { inputRef.current.disabled = false; inputRef.current.focus(); };

const update = (id, value, e) => { if (e.which === 13) { //here 13 is key code for enter key updateTodo({ id, item: value }); inputRef.current.disabled = true; } }; return ( <li key={item.id} className="card" > <textarea ref={inputRef} disabled={inputRef} defaultValue={item.item} onKeyPress={(e) => update(item.id, inputRef.current.value, e)} /> <div className="btns"> <button onClick={() => changeFocus()}> <AiFillEdit /> </button> {item.completed === false && ( <button style={{ color: "green" }} onClick={() => completeTodo(item.id)} > <IoCheckmarkDoneSharp /> </button> )} <button style={{ color: "red" }} onClick={() => removeTodo(item.id)} >

      &lt;IoClose /&gt;
    &lt;/button&gt;

  &lt;/div&gt;
  {item.completed &amp;&amp; &lt;span className=&quot;completed&quot;&gt;done&lt;/span&gt;}
   
&lt;/li&gt;

); };

export default TodoItem;

Last but not least, we have to add all the operations, such as add, complete, remove and update, to the code. Update DisplayTodos.js with the following code.

import React, { useState } from "React";
import { connect } from "React-Redux";
import {
addTodos,
completeTodos,
removeTodos,
updateTodos,
} from "../Redux/reducer";
import TodoItem from "./TodoItem";

const mapStateToProps = (state) => { return { todos: state, }; };

const mapDispatchToProps = (dispatch) => { return { addTodo: (obj) => dispatch(addTodos(obj)), removeTodo: (id) => dispatch(removeTodos(id)), updateTodo: (obj) => dispatch(updateTodos(obj)), completeTodo: (id) => dispatch(completeTodos(id)), }; };

const DisplayTodos = (props) => { const [sort, setSort] = useState("active"); return ( <div className="displaytodos"> <div className="buttons">

    &lt;button
      onClick={() =&gt; setSort(&quot;active&quot;)}
    &gt;
      Active
    &lt;/button&gt;

    &lt;button
      onClick={() =&gt; setSort(&quot;completed&quot;)}
    &gt;
      Completed
    &lt;/button&gt;

    &lt;button
      onClick={() =&gt; setSort(&quot;all&quot;)}
    &gt;
      All
    &lt;/button&gt;

  &lt;/div&gt;

  &lt;ul&gt;

      {props.todos.length &gt; 0 &amp;&amp; sort === &quot;active&quot;
        ? props.todos.map((item) =&gt; {
            return (
              item.completed === false &amp;&amp; (
       
                &lt;TodoItem
                  key={item.id}
                  item={item}
                  removeTodo={props.removeTodo}
                  updateTodo={props.updateTodo}
                  completeTodo={props.completeTodo}
                /&gt;
                    
              )
            );
          })
        : null}
      {/* for completed items */}
      {props.todos.length &gt; 0 &amp;&amp; sort === &quot;completed&quot;
        ? props.todos.map((item) =&gt; {
            return (
              item.completed === true &amp;&amp; (
                &lt;TodoItem
                  key={item.id}
                  item={item}
                  removeTodo={props.removeTodo}
                  updateTodo={props.updateTodo}
                  completeTodo={props.completeTodo}
                /&gt;
              )
            );
          })
        : null}
      {/* for all items */}
      {props.todos.length &gt; 0 &amp;&amp; sort === &quot;all&quot;
        ? props.todos.map((item) =&gt; {
            return (
              &lt;TodoItem
                key={item.id}
                item={item}
                removeTodo={props.removeTodo}
                updateTodo={props.updateTodo}
                completeTodo={props.completeTodo}
              /&gt;
            );
          })
        : null}

  &lt;/ul&gt;
&lt;/div&gt;

); };

export default connect(mapStateToProps, mapDispatchToProps)(DisplayTodos);

That's it. Now, use the npm start command to execute the above code.

We have learned what Redux is in React, its functioning along with state management, why we should use Redux in React, and how to create a simple Todo list app with the help of React and Redux.

Redux is an essential part of building a React app. Pure functions like reducers are used to handle storing applications data and actions are functions that are passed to store.dispatch() before they are sent to the store. Reducers have the ability to modify the state, which is why they are used for the app's logic.

Author

  • How to Build React Apps Using Redux as an Expert

    Sanskriti Singh

    Sanskriti is a tech writer and a freelance data scientist. She has rich experience into writing technical content and also finds interest in writing content related to mental health, productivity and self improvement.

Frequently Asked Questions

React Redux provides bindings for React UI to Redux. React components can read data from a Redux store and update the state using actions.

If you are new to React and Redux, you should start with the official Redux+JS template for Create React App, integrating Redux Toolkit and React Redux into the React framework.

Redux is not necessary for all apps. Understanding the kind of application you are building, the problems you need to solve, and which tools are most effective will help you create a successful application.

The Redux library is a standalone JS library. You can create and use a Redux store without a user interface. Additionally, you can use Redux without a UI framework and on a client and server. This means you can use it with any UI framework. With Redux, you can write applications using React, Vue, Angular, Ember, jQuery, or Vanilla JavaScript frameworks.

View more FAQs
Press

Press

What’s up with Turing? Get the latest news about us here.
Blog

Blog

Know more about remote work. Checkout our blog here.
Contact

Contact

Have any questions? We’d love to hear from you.

Hire remote developers

Tell us the skills you need and we'll find the best developer for you in days, not weeks.