React

React

Tutorial React: Estado global con Redux Toolkit

React y Redux Toolkit tutorial completo. Aprende a gestionar el estado global en aplicaciones React, configuración del store, slices, y lógica asíncrona.

Qué es y cómo se instala Redux Toolkit

Redux Toolkit es una biblioteca oficial de Redux que facilita la configuración y el uso de Redux en aplicaciones de React. Proporciona una serie de utilidades y patrones recomendados para simplificar la creación de stores, reducers y acciones, además de ofrecer soporte para lógica asíncrona con thunks.

Para instalar Redux Toolkit en una aplicación de React, sigue estos pasos:

Instalación de Redux Toolkit y React-Redux: Utiliza npm o yarn para instalar las dependencias necesarias. Redux Toolkit incluye Redux y otras dependencias útiles, mientras que React-Redux es la biblioteca oficial de enlaces entre React y Redux.

npm install @reduxjs/toolkit react-redux

o

yarn add @reduxjs/toolkit react-redux

Creación y uso de store

El store en Redux es el objeto que contiene el estado global de la aplicación. Con Redux Toolkit, la creación y configuración del store se simplifica gracias a la función configureStore. Esta función no solo crea el store, sino que también configura automáticamente el middleware y las herramientas de desarrollo recomendadas, como redux-thunk y redux-devtools-extension.

Para crear y usar un store en una aplicación de React con Redux Toolkit, sigue estos pasos:

1.Configuración del store: Crea un archivo, por ejemplo store.js, y utiliza configureStore para configurar el store. Importa los reducers de tus slices y añádelos al store.

// store.js
import { configureStore } from '@reduxjs/toolkit';
import contadorReducer from './features/contador/contadorSlice';

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

2.Proveer el store a la aplicación: Utiliza el componente Provider de react-redux para proveer el store a tu aplicación de React. Esto permite que cualquier componente de la aplicación pueda acceder al estado global.

// App.jsx
import { Provider } from 'react-redux';
import { store } from './store';
import Contador from './components/Contador/Contador';

export default function App() {
  return (
    <Provider store={store}>
      <Contador />
    </Provider>
  );
}

3.Uso de hooks de React-Redux: Para interactuar con el store desde los componentes de React, usa los hooks useSelector y useDispatch. useSelector se utiliza para leer valores del estado global, mientras que useDispatch se usa para despachar acciones.

// components/Contador/Contador.jsx
import { useSelector, useDispatch } from 'react-redux';
import { incrementar, decrementar } from '../../reducers/contador.reducer';

export default function Contador() {
  const valor = useSelector((state) => state.contador.valor);
  const dispatch = useDispatch();

  return (
    <div>
      <p>{valor}</p>
      <button onClick={() => dispatch(incrementar())}>Incrementar</button>
      <button onClick={() => dispatch(decrementar())}>Decrementar</button>
    </div>
  );
}

Estos pasos te permitirán configurar y utilizar el store en tu aplicación de React utilizando Redux Toolkit, facilitando la gestión del estado global de manera eficiente y siguiendo las mejores prácticas recomendadas.

Creación y uso de slice

Un slice en Redux Toolkit representa una porción del estado global y define los reducers y acciones relacionados con esa porción. La función createSlice simplifica la creación de slices al combinar la definición del estado inicial, los reducers y las acciones en un solo lugar.

Para crear y usar un slice en una aplicación de React con Redux Toolkit, sigue estos pasos:

1.Definir el slice: Crea un archivo, por ejemplo contadorSlice.js, donde definirás el slice utilizando createSlice. Especifica el nombre del slice, el estado inicial y los reducers.

// reducers/contador.reducer.js
import { createSlice } from '@reduxjs/toolkit';

const contadorSlice = createSlice({
  name: 'contador',
  initialState: { valor: 0 },
  reducers: {
    incrementar: (state) => {
      state.valor += 1;
    },
    decrementar: (state) => {
      state.valor -= 1;
    },
  },
});

export const { incrementar, decrementar } = contadorSlice.actions;

export default contadorSlice.reducer;

2.Añadir el slice al store: Importa el reducer del slice y añádelo al store configurado en store.js.

// store.js
import { configureStore } from '@reduxjs/toolkit';
import contadorReducer from './reducers/contador.reducer';

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

3.Proveer el store a la aplicación: Utiliza el componente Provider de react-redux para proveer el store a tu aplicación de React.

// App.jsx
import { Provider } from 'react-redux';
import { store } from './store';
import Contador from './components/Contador/Contador';

export default function App() {
  return (
    <Provider store={store}>
      <Contador />
    </Provider>
  );
}

4.Uso de hooks de React-Redux: Utiliza los hooks useSelector y useDispatch para interactuar con el estado global y las acciones en tus componentes.

// components/Contador/Contador.jsx
import { useSelector, useDispatch } from 'react-redux';
import { incrementar, decrementar, incrementarPorCantidad } from '../../reducers/contador.reducer';

export default function Contador() {
  const valor = useSelector((state) => state.contador.valor);
  const dispatch = useDispatch();

  return (
    <div>
      <p>{valor}</p>
      <button onClick={() => dispatch(incrementar())}>Incrementar</button>
      <button onClick={() => dispatch(decrementar())}>Decrementar</button>
      <button onClick={() => dispatch(incrementarPorCantidad(5))}>Incrementar por 5</button>
    </div>
  );
}

5.Acciones y reducers adicionales: Puedes añadir tantas acciones y reducers como necesites en tu slice. Aquí hay un ejemplo de cómo añadir una acción para incrementar por una cantidad específica.

// reducers/contador.reducer.js
import { createSlice } from '@reduxjs/toolkit';

const contadorSlice = createSlice({
  name: 'contador',
  initialState: { valor: 0 },
  reducers: {
    incrementar: (state) => {
      state.valor += 1;
    },
    decrementar: (state) => {
      state.valor -= 1;
    },
    incrementarPorCantidad: (state, action) => {
      state.valor += action.payload;
    },
  },
});

export const { incrementar, decrementar, incrementarPorCantidad } = contadorSlice.actions;

export default contadorSlice.reducer;

Este enfoque modularizado y estructurado te permitirá gestionar el estado global de tu aplicación de manera eficiente y siguiendo las mejores prácticas con Redux Toolkit y React.

Thunks y solicitudes asíncronas

En aplicaciones de React, es común realizar solicitudes asíncronas para interactuar con APIs externas. Redux Toolkit facilita la gestión de estos flujos asíncronos mediante la integración con redux-thunk. Un thunk es una función que se puede despachar como una acción, pero en lugar de ser una acción pura, puede contener lógica asíncrona.

Para manejar solicitudes asíncronas con Redux Toolkit, sigue estos pasos:

Configurar el middleware thunk: Redux Toolkit incluye redux-thunk por defecto, por lo que no es necesario configurarlo manualmente. El middleware thunk permite escribir creadores de acciones que devuelven una función en lugar de una acción.

1.Crear un thunk: Define un thunk utilizando la función createAsyncThunk de Redux Toolkit. Esta función genera automáticamente acciones para los estados de pending, fulfilled y rejected de la solicitud asíncrona.

// reducers/user.reducer.js 
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
import axios from 'axios';

const initialState = {
  user: {
    firstName: "none",
    age: 0,
    birthDate: "xxxx-xx-xx"
  },
  status: 'idle',
  error: null,
}

export const fetchUsuarios = createAsyncThunk(
  'usuario/fetchUsuario',
  async () => {
    const response = await axios.get('https://dummyjson.com/users/1');
    return response.data;
  }
);

const usuarioSlice = createSlice({
  name: 'usuario',
  initialState,
  reducers: {},
  extraReducers: (builder) => {
    builder
      .addCase(fetchUsuarios.pending, (state) => {
        state.status = 'loading';
      })
      .addCase(fetchUsuarios.fulfilled, (state, action) => {
        state.status = 'succeeded';
        state.user = action.payload;
      })
      .addCase(fetchUsuarios.rejected, (state, action) => {
        state.status = 'failed';
        state.error = action.error.message;
      });
  },
});

export default usuarioSlice.reducer;

2.Añadir el reducer al store: Importa el reducer del slice y añádelo al store configurado.

// store.js
import { configureStore } from '@reduxjs/toolkit';
import usuarioReducer from './reducers/user.reducer';

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

3.Despachar el thunk desde un componente: Utiliza el hook useDispatch para despachar el thunk desde un componente de React.

// components/PerfilUsuario.jsx
import { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { fetchUsuarios } from '../../reducers/user.reducer';

export default function PerfilUsuario() {
  const dispatch = useDispatch();
  const { user } = useSelector(state => state.usuario);

  useEffect(() => {
    dispatch(fetchUsuarios());
  }, [dispatch]);

  return (
    <div>
      <p>Nombre: {user.firstName}</p>
      <p>Edad: {user.age}</p>
      <p>Fecha de nacimiento: {user.birthDate}</p>
    </div>
  );
}

4.Manejo de estados asíncronos en los componentes: Utiliza los estados status y error para manejar las diferentes fases de la solicitud asíncrona en los componentes.

// components/PerfilUsuario.jsx
import { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { fetchUsuarios } from '../../reducers/user.reducer';

export default function PerfilUsuario() {
  const dispatch = useDispatch();
  const { user, status, error } = useSelector(state => state.usuario);

  useEffect(() => {
    dispatch(fetchUsuarios());
  }, [dispatch]);

  return (
    <div>
      <small>{status}</small>
      <p>Nombre: {user.firstName}</p>
      <p>Edad: {user.age}</p>
      <p>Fecha de nacimiento: {user.birthDate}</p>
      {error && <small>{error}</small>}
    </div>
  );
}

Con estos pasos, puedes gestionar solicitudes asíncronas en tu aplicación de React utilizando Redux Toolkit y thunks, asegurándote de manejar correctamente los estados de carga, éxito y error.

Ejemplo completo de Redux Toolkit en React

Para ilustrar cómo integrar Redux Toolkit en una aplicación de React, crearemos un ejemplo completo que incluye la configuración del store, la creación de un slice, la gestión de acciones asíncronas con thunks y la interacción con el estado global desde los componentes de React.

Configuración del store

Crea un archivo store.js para configurar el store utilizando configureStore de Redux Toolkit. Este store contendrá el estado global de la aplicación.

// store.js
import { configureStore } from '@reduxjs/toolkit';
import contadorReducer from './reducers/contador.reducer';
import usuarioReducer from './reducers/user.reducer';

export const store = configureStore({
  reducer: {
    contador: contadorReducer,
    usuario: usuarioReducer,
  },
});

Creación de slices

Crea un slice para gestionar el contador en features/contador/contadorSlice.js:

// reducers/contador.reducer.js
import { createSlice } from '@reduxjs/toolkit';

const contadorSlice = createSlice({
  name: 'contador',
  initialState: { valor: 0 },
  reducers: {
    incrementar: (state) => {
      state.valor += 1;
    },
    decrementar: (state) => {
      state.valor -= 1;
    },
    incrementarPorCantidad: (state, action) => {
      state.valor += action.payload;
    },
  },
});

export const { incrementar, decrementar, incrementarPorCantidad } = contadorSlice.actions;

export default contadorSlice.reducer;

Crea otro slice para gestionar los usuarios y las solicitudes asíncronas en features/usuarios/usuariosSlice.js:

// reducers/user.reducer.js 
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
import axios from 'axios';

const initialState = {
  user: {
    firstName: "none",
    age: 0,
    birthDate: "xxxx-xx-xx"
  },
  status: 'idle',
  error: null,
}

export const fetchUsuarios = createAsyncThunk(
  'usuario/fetchUsuario',
  async () => {
    const response = await axios.get('https://dummyjson.com/users/1');
    return response.data;
  }
);

const usuarioSlice = createSlice({
  name: 'usuario',
  initialState,
  reducers: {},
  extraReducers: (builder) => {
    builder
      .addCase(fetchUsuarios.pending, (state) => {
        state.status = 'loading';
      })
      .addCase(fetchUsuarios.fulfilled, (state, action) => {
        state.status = 'succeeded';
        state.user = action.payload;
      })
      .addCase(fetchUsuarios.rejected, (state, action) => {
        state.status = 'failed';
        state.error = action.error.message;
      });
  },
});

export default usuarioSlice.reducer;

Proveer el store a la aplicación

Utiliza el componente Provider de react-redux para proveer el store a tu aplicación en App.jsx:

// App.jsx
import { Provider } from 'react-redux';
import { store } from './store';
import Contador from './components/Contador/Contador';
import PerfilUsuario from './components/PerfilUsuario/PerfilUsuario';

export default function App() {
  return (
    <Provider store={store}>
      <Contador />
      <PerfilUsuario />
    </Provider>
  );
}

Componentes de React

Crea un componente para el contador en components/Contador/Contador.jsx:

// components/Contador/Contador.jsx
import { useSelector, useDispatch } from 'react-redux';
import { incrementar, decrementar, incrementarPorCantidad } from '../../reducers/contador.reducer';

export default function Contador() {
  const valor = useSelector((state) => state.contador.valor);
  const dispatch = useDispatch();

  return (
    <div>
      <p>{valor}</p>
      <button onClick={() => dispatch(incrementar())}>Incrementar</button>
      <button onClick={() => dispatch(decrementar())}>Decrementar</button>
      <button onClick={() => dispatch(incrementarPorCantidad(5))}>Incrementar por 5</button>
    </div>
  );
}

Crea un componente para gestionar los usuarios en components/Usuarios/Usuarios.jsx:

// components/PerfilUsuario.jsx
import { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { fetchUsuarios } from '../../reducers/user.reducer';

export default function PerfilUsuario() {
  const dispatch = useDispatch();
  const { user, status, error } = useSelector(state => state.usuario);

  useEffect(() => {
    dispatch(fetchUsuarios());
  }, [dispatch]);

  return (
    <div>
      <small>{status}</small>
      <p>Nombre: {user.firstName}</p>
      <p>Edad: {user.age}</p>
      <p>Fecha de nacimiento: {user.birthDate}</p>
      {error && <small>{error}</small>}
    </div>
  );
}
Certifícate en React con CertiDevs PLUS

Ejercicios de esta lección Estado global con Redux Toolkit

Evalúa tus conocimientos de esta lección Estado global con Redux Toolkit con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.

Todas las lecciones de React

Accede a todas las lecciones de React y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.

Introducción A React Y Su Ecosistema

React

Introducción Y Entorno

Instalar React Y Crear Nuevo Proyecto

React

Introducción Y Entorno

Introducción A Jsx

React

Componentes

Introducción A Componentes

React

Componentes

Componentes Funcionales

React

Componentes

Eventos En React

React

Componentes

Props Y Manejo De Datos Entre Componentes

React

Componentes

Renderizado Condicional

React

Componentes

Renderizado Iterativo Con Bucles

React

Componentes

Manejo De Clases Y Estilos

React

Componentes

Introducción A Los Hooks

React

Hooks

Estado Y Ciclo De Vida De Los Componentes

React

Hooks

Hooks Para Manejo De Estado Y Efectos Secundarios

React

Hooks

Hooks Para Gestión De Estado Complejo Y Contexto

React

Hooks

Hooks Para Optimización Y Actualizaciones Concurrentes

React

Hooks

Introducción A React Router

React

Navegación Y Enrutamiento

Definición Y Manejo De Rutas

React

Navegación Y Enrutamiento

Rutas Anidadas Y Rutas Dinámicas

React

Navegación Y Enrutamiento

Navegación Programática Y Redireccionamiento

React

Navegación Y Enrutamiento

Nuevos Métodos Create De React Router

React

Navegación Y Enrutamiento

Solicitudes Http Con Fetch Api

React

Interacción Http Con Backend

Solicitudes Http Con Axios

React

Interacción Http Con Backend

Estado Local Con Usestate Y Usereducer

React

Servicios Y Gestión De Estado

Estado Global Con Context Api

React

Servicios Y Gestión De Estado

Estado Global Con Redux Toolkit

React

Servicios Y Gestión De Estado

Custom Hooks Para Servicios Compartidos

React

Servicios Y Gestión De Estado

Certificados de superación de React

Supera todos los ejercicios de programación del curso de React y obtén certificados de superación para mejorar tu currículum y tu empleabilidad.

En esta lección

Objetivos de aprendizaje de esta lección

  • Entender qué es Redux Toolkit y cómo instalarlo.
  • Configurar el store de Redux Toolkit en una aplicación React.
  • Crear y usar slices para gestionar partes del estado global.
  • Utilizar hooks de React-Redux (useSelector, useDispatch) para interactuar con el estado y acciones.
  • Implementar lógica asíncrona con thunks y manejar estados de carga, éxito y error en componentes React.
  • Integrar completamente Redux Toolkit en una aplicación práctica.