Publicada:

React + Redux Toolkit - Obtenga (fetch) datos en una acción asíncrona con createAsyncThunk

Tutorial creado con React 18.1.0, Redux 4.2.0 y Redux Toolkit 1.8.2

Este es un ejemplo rápido de cómo obtener datos de una API en Redux usando una acción asíncrona creada con la función createAsyncThunk() de Redux Toolkit.

Los fragmentos de código a continuación son de un tutorial de autenticación de React + Redux JWT que publiqué recientemente que incluye una demostración en vivo, así que para ver el código en ejecución, consulte React 18 + Redux - Ejemplo y tutorial de autenticación JWT.

 

Rebanada de usuarios de Redux

Ruta: /src/_store/users.slice.js

La división de usuarios administra el estado Redux, las acciones y los reductores para los usuarios en la aplicación React. Cada parte del segmento está organizada en su propia función que se llama desde la parte superior del archivo para que sea más fácil ver lo que está pasando. initialState define las propiedades de estado en este segmento con sus valores iniciales. La propiedad users se utiliza para almacenar todos los usuarios obtenidos de la API. Por defecto es un objeto vacío y puede contener uno de los siguientes valores:

  • {} - estado inicial.
  • { loading: true } - los usuarios se obtienen actualmente de la API.
  • [{ ... }, { ... }, { ... }] - matriz de usuarios devueltos por la API.
  • { error: { message: 'un mensaje de error' } } - la solicitud a la API falló y se devolvió un error.

Acciones asíncronas con createAsyncThunk()

El objeto extraActions contiene lógica para acciones asincrónicas (cosas por las que debe esperar), como solicitudes de API. Las acciones asíncronas se crean con la función createAsyncThunk() de Redux Toolkit. El primer parámetro para createAsyncThunk es el nombre de la acción, la convención estándar para los nombres de acción de Redux es '[slice name]/[action name]' p. ('users/getAll'). El segundo parámetro es la función asíncrona que realiza la acción y devuelve el resultado cuando finaliza.

Para cada acción asíncrona creada con createAsyncThunk(), el kit de herramientas de Redux genera automáticamente tres acciones Redux, una para cada etapa de la acción asíncrona: pending, fulfilled, rejected.

El objeto extraReducers contiene métodos para actualizar el estado de Redux en cada una de las tres etapas diferentes de las acciones asincrónicas generadas por createAsyncThunk(), y el objeto se pasa como parámetro a la función createSlice() para incluir los reductores adicionales en el segmento de Redux.

El método de acción getAll() obtiene los usuarios de la API, en caso de éxito (fulfilled) la matriz de usuarios devuelta (action.payload) se almacena en la propiedad users del estado de Redux. La acción getAll se envía al almacén Redux y los usuarios se representan en el componente Inicio a continuación.

Exportar acciones y reductor para Redux Slice

La exportación de userActions incluye todas las acciones de sincronización (slice.actions) y las acciones asíncronas (extraActions) para el segmento de usuarios.

El reductor para el segmento de usuarios se exporta como usersReducer, que se usa en el almacén Redux raíz para configurar el estado global para la aplicación React.

import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';

import { fetchWrapper } from '_helpers';

// create slice

const name = 'users';
const initialState = createInitialState();
const extraActions = createExtraActions();
const extraReducers = createExtraReducers();
const slice = createSlice({ name, initialState, extraReducers });

// exports

export const userActions = { ...slice.actions, ...extraActions };
export const usersReducer = slice.reducer;

// implementation

function createInitialState() {
    return {
        users: {}
    }
}

function createExtraActions() {
    const baseUrl = `${process.env.REACT_APP_API_URL}/users`;

    return {
        getAll: getAll()
    };    

    function getAll() {
        return createAsyncThunk(
            `${name}/getAll`,
            async () => await fetchWrapper.get(baseUrl)
        );
    }
}

function createExtraReducers() {
    return {
        ...getAll()
    };

    function getAll() {
        var { pending, fulfilled, rejected } = extraActions.getAll;
        return {
            [pending]: (state) => {
                state.users = { loading: true };
            },
            [fulfilled]: (state, action) => {
                state.users = action.payload;
            },
            [rejected]: (state, action) => {
                state.users = { error: action.error };
            }
        };
    }
}
 

Almacén Redux

Ruta: /src/_store/index.js

El archivo de índice del store configura el almacén raíz de Redux para la aplicación React con la función configureStore(). El almacén de Redux devuelto contiene las propiedades de estado auth y users que se asignan a sus segmentos correspondientes.

El archivo de índice también vuelve a exportar todos los módulos de los segmentos de Redux en la carpeta. Esto permite que los módulos de Redux se importen directamente desde la carpeta _store sin la ruta al archivo de segmento. También permite realizar importaciones múltiples desde diferentes archivos a la vez (por ejemplo, import { store, authActions } from '_store';)

import { configureStore } from '@reduxjs/toolkit';

import { authReducer } from './auth.slice';
import { usersReducer } from './users.slice';

export * from './auth.slice';
export * from './users.slice';

export const store = configureStore({
    reducer: {
        auth: authReducer,
        users: usersReducer
    },
});
 

Componente de inicio de React

Ruta: /src/home/Home.jsx

La página de inicio se muestra después de iniciar sesión en la aplicación, muestra el nombre del usuario que inició sesión más una lista de todos los usuarios en la aplicación del tutorial. Los usuarios se cargan en el estado de Redux llamando a dispatch(userActions.getAll()); desde la función de gancho useEffect(), se recuperan los usuarios y se actualiza el estado de Redux en segmento de usuarios.

La lista de usuarios se muestra si la propiedad de estado users contiene una matriz con al menos 1 elemento, lo que se confirma comprobando {users.length && ...}.

Se muestra una rueda giratoria de carga mientras la solicitud de la API para los usuarios está en curso o se está cargando, y se muestra un mensaje de error si la solicitud falla.

Los valores de estado de Redux se recuperan para los datos auth y users con la ayuda de la función de enlace useSelector().


import { useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';

import { userActions } from '_store';

export { Home };

function Home() {
    const dispatch = useDispatch();
    const { user: authUser } = useSelector(x => x.auth);
    const { users } = useSelector(x => x.users);

    useEffect(() => {
        dispatch(userActions.getAll());
        
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, []);

    return (
        <div>
            <h1>Hi {authUser?.firstName}!</h1>
            <p>You're logged in with React 18 + Redux & JWT!!</p>
            <h3>Users from secure api end point:</h3>
            {users.length &&
                <ul>
                    {users.map(user =>
                        <li key={user.id}>{user.firstName} {user.lastName}</li>
                    )}
                </ul>
            }
            {users.loading && <div className="spinner-border spinner-border-sm"></div>}
            {users.error && <div className="text-danger">Error loading users: {users.error.message}</div>}
        </div>
    );
}
 


Suscríbete o Sígueme para actualizaciones

Suscríbete a mi canal de YouTube o sígueme en Twitter, Facebook o GitHub para recibir notificaciones cuando publique contenido nuevo.

Aparte de la codificación...

Actualmente estoy intentando viajar por Australia en motocicleta con mi esposa Tina en un par de Royal Enfield Himalayan. Puedes seguir nuestras aventuras en YouTube, Instagram y Facebook.


¿Necesita Ayuda React?

Buscar fiverr para encontrar ayuda rápidamente de desarrolladores React experimentados.