No tienes acceso a esta clase

隆Contin煤a aprendiendo! 脷nete y comienza a potenciar tu carrera

Redux Toolkit: createAsyncThunk

21/22
Recursos

Aportes 12

Preguntas 1

Ordenar por:

驴Quieres ver m谩s aportes, preguntas y respuestas de la comunidad?

o inicia sesi贸n.

Redux toolkit usado con react-query es muy poderoso. Creo que esta herramienta se merece todo un curso a parte.

No s茅, tal vez soy yo, pero鈥 es que la profe se come muchas partes importantes de la explicacion, tal vez las supone obvias, pero en realidad creo que este curso se merece un Remake, la segu铆 con mucho esfuerzo hasta aqu铆, pero no me anda la App ni a tiros desde que empez贸 con toolkit

Creo que la maestra olvido implementar 鈥渃onfigureStore鈥 de Redux toolkit, ya que para crear el store seguimos usando el metodo legacy 鈥渃reateStore鈥 importado de redux.

Leyendo la documentacion me quedo de esta manera:

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

import dataReducer from './slices/dataSlice';
import uiReducer from './slices/uiSlice';

export const store = configureStore({
  reducer: {
    data: dataReducer,
    ui: uiReducer,
  },
});

// Infer the `RootState` and `AppDispatch` types from the store itself
export type RootState = ReturnType<typeof store.getState>;
// Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState}
export type AppDispatch = typeof store.dispatch;

Y asi, el codigo en el archivo index queda mucho mas limpio (ya no necesitamos hacer la validacion del compose para usare el compose correcto):

import React from 'react';
import ReactDOM from 'react-dom/client';
import { Provider } from 'react-redux';

import App from './App';
import { store } from './store';

import './index.css';

const root = ReactDOM.createRoot(
  document.getElementById('root') as HTMLElement
);

root.render(
  <React.StrictMode>
    <Provider store={store}>
      <App />
    </Provider>
  </React.StrictMode>
);
 

Tambien al hacer esto, ya no necesitamos el root reducer, asi que elmine la carpeta 鈥渞educers鈥 y elimine las depencias de thunk y redux-thunk.

muy bueno y f谩cil con redux-toolkit

隆Creo que mejor贸 mucho el c贸digo con redux-tookit!

Una vez m谩s vuelve a hacer cambios que no muestra. Como quitar el hardcoding de loading que hace a false. Si no te acuerda de esto, te quedas loco pensando porqu茅 a ti no te aparece el spin

Hola a todos, les dejo mi codigo toolkit - ts - vite con algunas modificaciones respecto a la clase:

// main.tsx
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
import { Provider } from "react-redux";
import { store } from './slices';

ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
  <React.StrictMode>
    <Provider store={store} >
      <App />
    </Provider>
  </React.StrictMode>
)

// slices/index.ts
import { configureStore } from "@reduxjs/toolkit";
import { TypedUseSelectorHook, useDispatch, useSelector } from "react-redux";
import { dataReducer } from "./dataSlice";
import { uiReducer } from "./uiSlice";

const store = configureStore({
    reducer: {
        data: dataReducer,
        ui : uiReducer
    }
})

type RootState = ReturnType<typeof store.getState>

type Appdispatch = typeof store.dispatch

export const useAppDispatch : ()=> Appdispatch = useDispatch;

export const useAppSelector : TypedUseSelectorHook<RootState> = useSelector;

export { store }
// slices/dataSlice.ts
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import { getPokemonDetails, getPokemons, PokemonDetailType, PokemonType } from "../api";
import { setLoading } from "./uiSlice";

type InitialState = {
    pokemons: PokemonDetailType[]
}

const initialState: InitialState = {
    pokemons: []
}

export const fetchPokemonsWithDetails = createAsyncThunk(
    'data/fetchPokemonsWithDetails',
    async (_,{dispatch}) =>{
        try {
            dispatch(setLoading(true))
            const pkmns = await getPokemons();
            const pkmnsDetailed = await Promise.all((pkmns as PokemonType[]).map(pkmn=>getPokemonDetails(pkmn)))
            dispatch(setPokemons(pkmnsDetailed))
            dispatch(setLoading(false))
        } catch (err) {
            console.error(err)
            dispatch(setLoading(false))
        }

    }
)

export const dataSlice = createSlice({
    name: 'data',
    initialState,
    reducers:{
        setPokemons: (state,action)=>{
            state.pokemons = action.payload
        },
        setFavorite: (state, action)=>{
            const currentPokemonIndex = state.pokemons.findIndex(
                (pkmn:PokemonDetailType) => {
                    return pkmn.id  === action.payload.pokemonId
                }
            )
            if(currentPokemonIndex >= 0){
                const isFavorite = state.pokemons[currentPokemonIndex].favorite
                state.pokemons[currentPokemonIndex].favorite = !isFavorite
            }
        }
    }
})

export const dataReducer = dataSlice.reducer;

export const { setPokemons, setFavorite } = dataSlice.actions;
// slices/uiSlice.ts
import { createSlice } from "@reduxjs/toolkit"

export type TypeState = {
    loading : boolean
}

const initialState:TypeState = {
    loading: false
}

const uiSlice = createSlice({
    name: 'ui',
    initialState,
    reducers: {
        setLoading: (state, action)=>{
            state.loading = action.payload
        }
    }
})

export const uiReducer = uiSlice.reducer;

export const { setLoading } = uiSlice.actions;

// App.tsx
import { useEffect } from 'react'
import { Search } from './components/Search'
import { PokemonList } from './components/PokemonList'
import { Col, Spin } from 'antd'
import { useAppDispatch, useAppSelector } from './slices'
import { fetchPokemonsWithDetails } from './slices/dataSlice'
import logo from './statics/logo.svg'
import './App.css'

function App() {
  const pokemons = useAppSelector((state)=>state.data.pokemons)
  const loading = useAppSelector((state)=>state.ui.loading)
  const dispatch = useAppDispatch();
  useEffect(()=>{
    dispatch(fetchPokemonsWithDetails())
  },[])
  return (
    <div className="App">
      <Col span={4} offset={10}>
        <img src={logo} alt="Pokedux" />
      </Col>
      <Col span={8} offset={8}>
        <Search />
      </Col>
      {loading?
      <Col offset={12} >
        <Spin spinning size='large' />
      </Col>
      :
      <PokemonList pokemons={pokemons} />
      }
    </div>
  )
}


export default App;

Que desastre como se explican estos temas tan importantes!

Algo que no se mencion贸 es modificar la configuraci贸n del store con @reduxjs/toolkit.
.
Esto simplifica mucho nuestro index.jsx, ya que incluye por defecto:

  • redux-thunk
  • Redux DevTool Extension
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App/index'
import './index.css'

import { rootReducer } from './reducers/rootReducer'
import { Provider } from 'react-redux'
import { configureStore } from '@reduxjs/toolkit'
import { logger,nameUpperCase } from './middlewares/index'

const store = configureStore({
  reducer: rootReducer,
  middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(logger, nameUpperCase)
});

ReactDOM.createRoot(document.getElementById('root')).render(
  <React.StrictMode>
    <Provider store={store}>
      <App />
    </Provider>
  </React.StrictMode>,
)

Moraleja, redux es, al menos hasta tener proyectos realmente grandes, usar las fases b谩sicas junto a middleware y redux toolkit.

Esta cool RTK. Tambien existe una nueva funcionalidad de RTK que es RTK Query que permite el manejo de queries y mutations de una forma mejorada. Compite directamente con React Query.

Por debajo funciona con este createAsyncThunk pero a帽ade m谩s funcionalidades.

https://redux.js.org/tutorials/essentials/part-7-rtk-query-basics#rtk-query-overview

En angular programamos con mucho menos C贸digo fuente