Solución:
Soy un mantenedor de Redux y creador de Redux Toolkit.
FWIW, nada sobre hacer llamadas asíncronas con cambios de Redux con Redux Toolkit.
Seguiría usando un middleware asíncrono (normalmente redux-thunk
), recupera datos y envía acciones con los resultados.
A partir de Redux Toolkit 1.3, tenemos un método auxiliar llamado createAsyncThunk
que genera los creadores de acciones y solicita el envío de acciones de ciclo de vida para usted, pero sigue siendo el mismo proceso estándar.
Este código de muestra de los documentos resume el uso;
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'
import { userAPI } from './userAPI'
// First, create the thunk
const fetchUserById = createAsyncThunk(
'users/fetchByIdStatus',
async (userId, thunkAPI) => {
const response = await userAPI.fetchById(userId)
return response.data
}
)
// Then, handle actions in your reducers:
const usersSlice = createSlice({
name: 'users',
initialState: { entities: [], loading: 'idle' },
reducers: {
// standard reducer logic, with auto-generated action types per reducer
},
extraReducers: {
// Add reducers for additional action types here, and handle loading state as needed
[fetchUserById.fulfilled]: (state, action) => {
// Add user to the state array
state.entities.push(action.payload)
}
}
})
// Later, dispatch the thunk as needed in the app
dispatch(fetchUserById(123))
Consulte la página de documentos de Redux Toolkit “Guía de uso: Lógica asíncrona y obtención de datos” para obtener información adicional sobre este tema.
¡Con suerte, eso te indicará la dirección correcta!
Usar redux-toolkit v1.3.0-alpha.8
Prueba esto
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
export const myAsyncInSlice = createAsyncThunk('bundles/myAsyncInSlice', () =>
getAxiosInstance()
.get("https://foroayuda.es/")
.then(ok => ok.data)
.catch(err => err),
);
const usersSlice = createSlice({
name: 'bundles',
initialState: {
bundles: [],
selectedBundle: null,
page: {
page: 0,
totalElements: 0,
size: 20,
totalPages: 0,
},
myAsyncResponse: null,
myAsyncResponseError: null,
},
reducers: {
// add your non-async reducers here
},
extraReducers: {
// you can mutate state directly, since it is using immer behind the scenes
[myAsyncInSlice.fulfilled]: (state, action) => {
state.myAsyncResponse = action.payload;
},
[myAsyncInSlice.rejected]: (state, action) => {
state.myAsyncResponseError = action.payload;
},
},
});
Puedes usar createAsyncThunk
crear thunk action
, que puede activarse mediante dispatch
teamSlice.ts
import {
createSlice,
createAsyncThunk,
} from "@reduxjs/toolkit";
const axios = require('axios');
export const fetchPlayerList = createAsyncThunk('team/playerListLoading',
(teamId:string) =>
axios
.get(`https://api.opendota.com/api/teams/${teamId}/players`)
.then(response => response.data)
.catch(error => error),
);
const teamInitialState = {
playerList: {
status: 'idle',
data: {},
error: {}
}
};
const teamSlice = createSlice({
name: 'user',
initialState: teamInitialState,
reducers: {},
extraReducers: {
[fetchPlayerList.pending.type]: (state, action) => {
state.playerList = {
status: 'loading',
data: {},
error: {}
};
},
[fetchPlayerList.fulfilled.type]: (state, action) => {
state.playerList = {
status: 'idle',
data: action.payload,
error: {}
};
},
[fetchPlayerList.rejected.type]: (state, action) => {
state.playerList = {
status: 'idle',
data: {},
error: action.payload,
};
},
}
});
export default teamSlice;
Componente Team.tsx
import React from "react";
import { useSelector, useDispatch } from "react-redux";
import { fetchPlayerList } from './teamSlice';
const Team = (props) => {
const dispatch = useDispatch();
const playerList = useSelector((state: any) => state.team.playerList);
return (
<div>
<button
onClick={() => { dispatch(fetchPlayerList('1838315')); }}
>Fetch Team players</button>
<p>API status {playerList.status}</p>
<div>
{ (playerList.status !== 'loading' && playerList.data.length) &&
playerList.data.map((player) =>
<div style={{display: 'flex'}}>
<p>Name: {player.name}</p>
<p>Games Played: {player.games_played}</p>
</div>
)
}
</div>
</div>
)
}
export default Team;