The problem of a React application without Redux

Introduction

Hello there(General Kenobi). Let’s talk a little bit about what Redux is and understand how we can implement this with react without much complication. Before we talk about redux, we need to understand a few things to make sure everyone is on the same page, since you can be a beginner or don’t have any prior experience with React. Don’t worry if you don’t know anything about react, because I will explain to you in a way that you will understand what kind of problem we are trying to solve here.

Understanding the Basics

Let’s see, Think everything is a block, and inside a block can have a child block and this child can receive information only if a child of the block has the information, but what does that means?

  1. For the blue block to receive information of the green block it needs to be inside the green block.

As you saw, We had a problem because if a block needs information that another component has, it’s necessary to move this to a component that is a father component in common for both components. Now, We have the solution for a problem like that, because we can move our information to the top block since the father for the components we need to share that information has both components inside.

The problem

Imagine, you have a complex and a large application and you need to pass data from a top-level component to a bottom-level component. That will probably be complex coding and giving data to a component that will never use it. We call it prop-drilling.

Redux

What is state management?

Since the start of this article, we only talked about how can we handle states across components and components with your own state. State management is about how we can solve this problem when your application grows.

What is Redux?

Redux is a library for managing application state.

Why Should I use Redux?

Like we saw before, managing states shared across components becomes difficult.

When Should I use Redux?

That’s a good question because those who work with react, know that there is another way to do It, and for those who want to know, I’m talking about React hooks, mobx, and others.

I’m not here to tell you what you should use, because It depends on what kind of application you are building and working on, but if the application is not so complex you can use React hooks.

Redux Terms

  • State is a object that describes parts of the application.

Redux Concepts

  • Actions in Redux: An action is basically a payload that describes and sends data from our application to our store.
{type: "todos/addTodo",payload: {text:"Redux"}}
  • Action Creators: Actions are created by action creators, that are called within the component and dispatch the action.
const addTodo = text => {
return {
type: 'todos/addTodo',
payload: text
}
}
  • Reducers in Redux: Reducers are pure functions that specify how the application’s state changes and return the new state. Reducers are not allowed to modify the existing state, its state is based on the new state, they don’t do any asynchronous logic and never save an obj like Datetime.
const todoReducer= (state = {}, action) => {
switch (action.type) {
case "todos/addTodo":
return {
...state,
...action.payload
};
default:
return state;
}
};
  • Store in Redux: Store is our application’s state, we can access the data and update it.
const store = createStore(todoReducer);
  • Dispatch: Dispatch is the only way to update the state.
store.dispatch(addTodo("Todo"))
  • Selectors: Basically selectors know how to get a specific piece of data from the store.
const getTodos = state => state.value//getState returns the current state 
const todos = getTodos(store.getState())

Step by Step(Redux toolkit)

Now we are going to see the entire flux with React and Redux. To practice, I chose the redux toolkit, because when I started to learn redux with react, It was difficult to understand, but when I start to use Redux toolkit I realize that It’s easier to understand React with Redux. You don’t need to write much code, the configuration setup is simple and Redux toolkit was built to solve a lot of boilerplate code.

  • First step: We need to import createSlice, this helper function allows us to define our reducer and initial state, also it takes care of the generation of the action creators, and types. If you take a closer look at the code in createSlice, there is a key named “name”, this name is the first part of the type of each reducer and the second part of our type is the key of each reducer. We have something like that, our first part of the type is the name “todos” + the second part it’s the key “addTodo”. Each action creator has the same name as the reducer function.
//src\todoSlice.js
import { createSlice } from '@reduxjs/toolkit'
const todoSlice = createSlice({
name: 'todos',
initialState: {
value: {}
},
reducers: {
addTodo: (state, action) => {
const {payload, type} = action;
state.value[payload] = {id: payload, value: payload};
}
}
})
export const { addTodo } = todoSlice.actions;
export default todoSlice.reducer;
  • Second step: With our todoSlice configured, we need to pass our reducer function, if you take a look back at the todoSlice, the reducers are exporting by default. So, we need just to add it inside the reducer argument in configureStore. If you have more than one slice, you just put it inside de reducer too. I will explain to you more later how you can access the data with more than one slice.
//src\store.js
import { configureStore } from '@reduxjs/toolkit'
import todoSlice from './todoSlice';
export default configureStore({
reducer: {
todos: todoSlice,
//system
}
})
  • Third step: For useSelector and useDispatch to work correctly we need to pass our store to them. For that, We need to import a Provider and wrap that around our App. Making that every component(block) can access this data.
//src\App.js 
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux'
import App from './App';
import store from './store';
ReactDOM.render(
<Provider store={store}>
<React.StrictMode>
<App />
</React.StrictMode>
</Provider>,
document.getElementById('root')
);
  • Fourth step: This component is responsible for adding a todo and it has its own state to save the text, It doesn’t make sense to save the input’s value in the store. So, here we dispatch an action creator that we export in “src\todoSlice.js” and import the useDispatch, because in this component we don’t have access at store.disptach, but the hook takes care of it and we just need to pass an action.
//src\form import React, {useState} from 'react';
import { useDispatch } from 'react-redux';
import {addTodo} from './todoSlice';
const Form = () => {
const [text, setText] = useState('');
const dispatch = useDispatch();
const onSaveTodo = () => {
dispatch(addTodo(text));
setText('');
}
return (
<>
<input onChange={(e) => setText(e.target.value)} value= {text}/>
<button onClick={() => onSaveTodo()} >Add</button> </>
);
}
export default Form;
  • Fifth step: It’s time to read data from the store and listen to their changes. Here we are importing the useSelector and selecting only the piece of information we need. If you take a look at the code in state, as I said before, if you have more than one slice in your application you can access the store data by state + (name you give to the reducer in creatingStore). This component will re-render your view when the data changes in the store “state.todos.value”.
import React from 'react';
import { useSelector } from 'react-redux';
const List = () => {
const todos = useSelector((state) => state.todos.value);
const values = Object.values(todos);
return (
<>
{
values.map((todo, index) => <div key={todo.id}>{index + 1} - {todo.value}</div>)
}
</>
);
}
export default List;
  • Sixth step: As I said if you pass the information across the aplication by moving it to a common parent to both components, but with redux, our App component is clean and it isn’t keeping any information that it doesn’t need.
import React from 'react';
import Form from './form';
import List from './List';
const App = () => {
return (
<div>
<Form/>
<List/>
</div>
);
}
export default App;

Conclusion

As you can see, Understanding and Implementing redux wasn’t so difficult, and using Redux toolkit we have just written a few lines of code. The solution about sharing information among components was easy to solve using Redux Toolkit and if you have a lot of components in your application, you won’t pass the information across the component that doesn’t need it. I highly recommend you read the documentation about redux toolkit and try to do some projects using it

React and Flutter developer