First steps with Redux

First steps with Redux

Published on: 08 February 2023

Introduction

Redux is a state container for Javascript apps. It serves as a library within React Apps but can also be associated with other Javascript frameworks.

Redux supports the development of large and complex applications that may need to take advantage of this container.

Redux is based on three fundamental concepts:

  • reducers
  • actions
  • action creators
  • store

Reducers

A reducer is a function that uses the previous state and an action as input and returns a new state as output. An action is an object with a type and an optional payload.

Here is an example of a Reducer:

function Reducer(previousState, action) => {
 // use the action type and payload to create a new state based on
 // the previous state.
 return newState;
}

Reducers allow you to specify how the state of applications changes in response to the actions deployed in the store.

If your app has multiple states, it can also have multiple reducers. The core functionality of your app should have its own reducer..

Action

An action is a simple Javascript object that represents the load of information that is sent from the application to your store. Each action has a type and an optional payload.

Major changes in applications using redux start with an event that is directly or indirectly triggered by a user. Events, such as clicking on a button, selecting objects or hovering the cursor over a particular element, trigger AJAX requests that send back some data. There are endless possibilities to associate an action as a response to an event.

Actions are created by an action creator.

ActionCreator

In Redux, an action creator is a feature that returns an action object. It may seem unnecessary but creators allow you to send an action object to all the different reducers in the app, ensuring a benefit in terms of portability and testing.

Depending on the action sent, reducers can return a new version of their state, which is passed into the application state and, finally, into the React app, by reloading the components.

According to the definition given by Action Creator, the function may have a syntax similar to the following:

export function newTask({ task }) {
 return {
   type: 'NEW_TASK',
   payload: {
     task,
     completed: false
   },
 }
}

// esempio di valore di ritorno:
// {
//   type: 'NEW_TASK',
//   todo: { task: 'Prepara valigia viaggio', completed: false },
// }

Example of an interaction between a reducer and an action of type NEW_TASK:

export default function(state = initialState, action) {
 switch (action.type) {
   case 'NEW_TASK':
     const newState = [...state, action.payload];
     return newState;


   default:
     return state;
 }
}

Depending on the involvement in the action, reducers will either return the same state as before or a new one. All reducers will process the action but only some of them will change their state.

Finally, the components will be rendered again:

{
 currentTask: { task: 'Prepara valigia viaggio', completed: false },
 todos: [
   { task: 'Prepara valigia viaggio', completed: false },
   { task: 'Lascia cane alla pensione', completed: true }
 ],
}

Combining Reducers

Redux ensures you the combineReducers feature to perform two tasks:

  • Generate a function that calls our reducers with the portion of the state selected based on their key.
  • Then combine the results back into one object.

The Store

The store is the object that includes the actions and reducers. Basically, it manages information about what is happening and state changes in response to those events.

The tasks of the store are:

  • Permission to access via getState()
  • Permission to update a state via dispatch(action)
  • Maintenance of the state of the entire application
  • Registration listeners via subscribe(listener)
  • Deregistrationlistenersvia the function returned by subscribe(listener)

To create a store, simply pass it a combination of reducers and then allow it to deploy actions.

import { createStore } from 'redux';
import todoReducer from './reducers';

const store = createStore(todoReducer);
store.dispatch(addTodo({ task: 'Finisci di leggere la guida'}));
store.dispatch(addTodo({ task: 'Applica i concetti imparati su un tuo progetto!' }));
//...

Data Flow in Redux

Redux has a fixed one-way data flow, which allows you to better understand the data lifecycle within your application.

The data lifecycle steps in Redux are as follows

export default const currentTask(state = {}, action){
 // deal with this piece of state
 return newState;
};

export default const todos(state = [], action){
 // deal with this piece of state
 return newState;
};

export default const todoApp = combineReducers({
 todos,
 currentTask,
});
  1. An event within your application triggers a call to store.dispatch(actionCreator(payload))
  2. The store calls the root reducer with the current state and action
  3. The root reducer combines the output of several reducers into a single state tree

Once the action is issued, todoApp will call both reducers and combine the result sets into a single state tree:

return {
 todos: nextTodos,
 currentTask: nextCurrentTask,
};

Once Redux saves the state tree, the new state tree will be the next in your app.

Conclusions

By the end of this guide, you'll have completed your smattering of Redux. Delve into the concepts learned and many more withthe Redux Official Documentation.