Buen aporte ese de que ahora Redux recomienda Redux toolkit por encima del. La verdad ni sabia.
Según su documentación se debe a que Redux toolkit simplifica el proceso, tiene mejores practicas y elimina codigo repetitivo.
Pero no encontre que fuera por cuestiones de rendimiento y que planean dejar el "createStore" API en la libreria.
Por eso me alivia que la profesora comento que ya lo íbamos a ver más adelante en el curso (aun no he llegado ahi), de esa manera estaremos actualizados.
No se en que momento lo comenta en este video, pero esto si está atrasado
En el minuto 11:47 inidica usar Redux toolkit que seria algo menos complejo, esta clase son solo para saber las bases de React Redux
mapStateToProps es una función recibe nuestro estado y retorna un objeto cuyas propiedades van a ser enviadas a las props del componente que se está conectado a redux.mapDispatchToProps es una función que recibe el dispatcher de redux y retorna un objeto que será mapedo a las propiedades con los action creatrorsbuen aporte:)
No entendi nada
Hola, Edward.
A mí también se me complicó un poco entender; tuve que ver el vídeo 3 veces.
Intenta ir paso a paso en tu código y ver qué se hizo para tratar de entender
Yo tampoco jajaja. No estas solo!
No puede explicarse tan mal esta clase. Se estan tomando por sabidos muchos conceptos que en ningun lado explican
El curso asume que ya sabes trabajar con redux, como se indica en la primera clase.
y de donde se supone que debemos sacar los conocimientos previos de redux si este es el unico curso que hay en Platzi sobre esto?
Primera Forma de Conectar Redux Con React
Le agrege un loading skeleton, utilizando el estado y la librería de estilos que la profe nos proporcionó al inicio del curso. Espero les Sirva a alguien y agredeceria el Feedback. Primero Se crean los Actions Types
const SET_POKEMONS= 'SET_POKEMONS'; const SET_ERROR= 'SET_ERROR'; export {SET_POKEMONS,SET_ERROR}
despues los Dispatch o actualizadores del estado
import { SET_ERROR, SET_POKEMONS } from "./types"; export const setError = (payload) => { return { type: SET_ERROR, payload, }; }; export const setPokemons = (payload) => ({ type: SET_POKEMONS, payload, });
Pasamos a crear el reducer con un estado inicial
import { SET_ERROR, SET_POKEMONS } from "../actions/types"; const initialState = { pokemons: [], loading:true, error:false }; export const pokemonsReducer = (state = initialState, action) => { switch (action.type) { case SET_POKEMONS: return { ...state, pokemons: action.payload, loading:false, }; case SET_ERROR: return { ...state, error:true } default: return state; } };
en el lugar que vallamos a utilizar el estado creamos las funciones para que se conecten a las props de nuestro componente
import { Searched } from './components/Searched'; import { connect} from 'react-redux' import {Col, Row} from 'antd' import './App.css' import { setError, setPokemons as setPokemosActions } from './actions'; import { PokemonList } from './components/PokemonList'; import { PokeSkeleton } from './components/PokeSkeleton'; import { useEffect } from 'react'; import { getPokemons } from './services/PokeApi'; function App({setError,loading,setPokemons,pokemons,error}) { useEffect(()=>{ getPokemons().then(res=>setPokemons(res.results)).catch(err=>setError(error)) },[]) return ( <div className="app"> <Col span={4} offset={10} style={{marginBottom:30}}> <img src='https://static.platzi.com/media/tmp/class-files/github/curso-redux/curso-redux-01-pokeapi/src/statics/logo.svg' alt='pokedux'/> </Col> <Col span={8} offset={8} > <Searched/> </Col> <Row style={{marginTop: 50 }} justify={'center'} gutter={20}> { loading ? <PokeSkeleton/>:<PokemonList pokemons={pokemons}/>} </Row> </div> ) } // mapea el stado del redux y para pasarlo a las props const mapStateToProps=state =>( { pokemons:state.pokemons, loading:state.loading, error:state.error } ); //mapea los activadores del estado para pasarlos a las props y asi consumirlos en //nuestro componente const mapDispatchToProps= dispatch=> ({ setPokemons:(value)=> dispatch(setPokemosActions(value)), setError:(value)=>dispatch(setError(value)) }); //utilizamos la functtion connect de react-redux para conectar los dispatch y el estado con las props del componente export default connect(mapStateToProps,mapDispatchToProps)(App);
y Por último en el índex de nuestra APP, envolvemos toda nuestra app con un provider que contenga todo el store.
import React from "react"; import ReactDOM from "react-dom/client"; import App from "./App"; import { pokemonsReducer } from "./reducers/pokemons"; import { Provider } from "react-redux"; import { legacy_createStore as createStore } from "redux"; // le pasamos nuestro reducer al store const store = createStore(pokemonsReducer); ReactDOM.createRoot(document.getElementById("root")).render( <Provider store={store}> <React.StrictMode> <App /> </React.StrictMode> </Provider> );
Excelente, me sirvió para entender mejor.
Aqui les dejo mi codigo utilizando utilizando typescript y vite. Estoy aplicando lo aprendido en otros cursos, si ven algo a mejorar comenten
// main.tsx import React from 'react' import ReactDOM from 'react-dom/client' import App from './App' import { pokemonReducer } from "./reducers/pokemon"; import { Provider } from "react-redux"; import { legacy_createStore as createStore } from 'redux' // import './index.css' const store = createStore(pokemonReducer); ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( <Provider store={store} > <React.StrictMode> <App /> </React.StrictMode> </Provider> )
// App.tsx import { useEffect, useState } from 'react' import { connect } from 'react-redux' import { Col } from 'antd' import { Search } from './components/Search' import { PokemonList } from './components/PokemonList' import { getPokemons, PokemonType } from './api' import logo from './statics/logo.svg' import './App.css' import { setPokemmons as setPokemmonsActions } from './actions' type AppType = { pokemons:PokemonType[], setPokemons:any } function App({pokemons, setPokemons}: AppType ) { // const [pokemons,setPokemons] = useState<PokemonType[]>([]); useEffect(()=>{ async function fetchPokemon(){ const pkmns = await getPokemons(); setPokemons(pkmns as PokemonType[]) } fetchPokemon(); },[]) return ( <div className="App"> <Col span={4} offset={10}> <img src={logo} alt="Pokedux" /> </Col> <Col span={8} offset={8}> <Search /> </Col> <PokemonList pokemons={pokemons} /> </div> ) } const mapStateToProps = (state:any)=>({ pokemons: state.pokemons }) const mapDispatchToProps = (dispath:any)=>({ setPokemons: (value:PokemonType[])=> dispath(setPokemmonsActions(value)) }) export default connect(mapStateToProps, mapDispatchToProps)(App)
// reducers/pokemon.ts import { SET_POKEMONS } from "../actions/types" import { PokemonType } from "../api" type TypeState = { pokemons: PokemonType[] } const initialState: TypeState = { pokemons: [] } export const pokemonReducer = (state:TypeState = initialState, action:any)=>{ switch(action.type){ case SET_POKEMONS: return {...state, pokemons: action.payload} default: return state } }
// actions/index.ts import { PokemonType } from "../api"; import { SET_POKEMONS } from "./types"; export const setPokemmons = (payload: PokemonType[])=>({ type: SET_POKEMONS, payload })
Sin dudas es la peor clase que he visto en platzi, solo superada por el curso de dart que había antes que estaba completamente desactualizado y solo era un profesor leyendo diapositivas. Aqui la profesora parece que solo pega comandos y lineas de codigo sin explicar a profundidad las cosas y la verdad es frustrante porque se supone que tienes platzi para que te expliquen bien, no para que te den mil vueltas y las explicaciones estén muy por encima. Deberian actualizar este curso
te amo redux xd
Como estoy haciendo este curso directamente se me esta complicando entender todo ya que no quise hacer el curso 'basico' de redux, por que esta muy desactualizado sea el de react router 5 y redux o el de redux por bedu
yo odiaba redux, ahora cuando estoy sin el me siento vacio, jajaja
por un momento pensé igual que tu, pero a pesar de estar "desactualizado" sigue vigente, yo estoy trabajando en un proyecto que pagan muy bien pero que tienen AngularJS (angular 1), te podrás imaginar lo literalmente desactualizado que está, el curso "básico" me pareció super importante y hace que este curso sea practicamente un saludo a la bandera, una frase que le digo a mis alumnos, si quieres correr, primero debes aprender a caminar, saludos.
Mi practica
main.jsx
import React from 'react' import ReactDOM from 'react-dom/client' import App from './App' import {pokemonsReducer} from "./reducers/pokemons"; import {Provider} from "react-redux"; import {legacy_createStore as createStore} from "redux"; import './index.css' const store = createStore(pokemonsReducer); ReactDOM.createRoot(document.getElementById('root')).render( <React.StrictMode> <Provider store={store}> <App/> </Provider> </React.StrictMode> )
App.jsx
import {Col} from 'antd'; import Searcher from "./components/Searcher"; import {useEffect} from 'react' import {connect} from 'react-redux' import PokemonList from "./components/PokemonList.jsx"; import {getPokemon} from "./api"; import {setPokemons as setPokemonsActions} from "./actions/index.js"; import Logo from "./assets/logo.svg"; import './App.css' function App({pokemons, setPokemons}) { useEffect(() => { const fetchPokemons = async () => { const response = await getPokemon(); setPokemons(response); } fetchPokemons(); }, []) return ( <div className="App"> <Col span={4} offset={10}> <img src={Logo} alt="pokeapi"/> </Col> <Col span={8} offset={8}> <Searcher/> </Col> <PokemonList pokemons={pokemons}/> </div> ) } const mapStateToProps = (state) => ({ pokemons: state.pokemons }); const mapDispatchToProps = (dispatch) => ({ setPokemons: (value) => dispatch(setPokemonsActions(value)) }) export default connect(mapStateToProps,mapDispatchToProps)(App)
reducers/pokemons.js
import {SET_POKEMON} from "../actions/types.js"; const initialState = {pokemons: []}; export const pokemonsReducer = (state, action) => { switch (action.type) { case SET_POKEMON: return {...state, pokemons: action.payload} break; default: return {...state}; break; } }
action/index.js
import {SET_POKEMON} from "./types"; export const setPokemons = (payload) => ({ type: SET_POKEMON, payload });
action/types.js
export const SET_POKEMON = 'SET_POKEMON';
Creo que este guión lo deberían refactorizar; sinceramente no se entiende la mayor parte de lo que hace en los primeros 5 minutos
Gracias por tu feedback.
¿Quien le pasa las props al componente APP?
Por si a alguien le surgio tambien esta duda, pues resulta que la funcion connect es quien provee de pokemons y setPokemons al componente APP
npm install redux react-redux
¿Cuáles son las ventajas/desventajas entre usar "connect" o "useDispatch, useSelector"?
Creo que el curso esta un poco desactualizado, además sinceramente creo que no se explica detenidamente los conceptos que se utilizan, necesitan mejorar esta parte muchísimo
Parece complicado al principio por todas las acciones que hay que hacer en el flujo del codigo, pero creo que a la larga se aprende todo.
Pero que montón de boilerplate, comparado con reduxt toolkit
No me quedó claro mapStateToProps ni mapDispatchToProps. También por qué hay que pasar estas dos funciones al connect del App
Básicamente: mapStateToProps sirve para recuperar el estado. Y mapDispatchToProps es para “despachar” o enviar acciones predefinidas anteriormente
Te dejo un articulo: https://code.tutsplus.com/es/tutorials/getting-started-with-redux-connecting-redux-with-react--cms-30352
Buenas. Por aqui dejo mi aporte. Por lo que estuve viendo e investigando, ya en redux no se utiliza la función legacy_createStore ni la de createStore; ahora se utiliza la función configureStore del paquete @reduxjs/toolkit. Anexo código de ejemplo:
import React from 'react'; import ReactDOM from 'react-dom/client'; import { Provider } from 'react-redux'; import { configureStore } from '@reduxjs/toolkit'; import { pokemonsReducer } from './reducers/pokemons'; import App from './App'; import './index.css'; const root = ReactDOM.createRoot(document.getElementById('root')); const store = configureStore({ reducer: pokemonsReducer }) root.render( <React.StrictMode> <Provider store={store}> <App /> </Provider> </React.StrictMode> );
Hay cosas que vienen del anterior curso, pero igual me perdi con esta explicacion, voy a tener que ver esta clase mas de 2 veces.
En mi caso preferí tener parte de la lógica en un sólo lugar y utilicé un objeto reductor en vez del switch por tema de legibilidad una vez crezca la cantidad de estados que agreguemos.
//Estado inicial const initialState = { pokemons : [], } //Tipos de acciones const actionType = { setPokemons : "Set Pokemons", } //Objeto reductor const objectReducer = (state, payload) => ({ [actionType.setPokemons] : { ...state, pokemons: payload, } }) //Función reductora la cual devuelve el estado actualizado function pokemonsReducer(state = initialState, action){ return objectReducer(state, action.payload)[action.type] || state; } //Acciones creadoras const handleSetPokemons = (payload)=>( { type :actionType.setPokemons, payload, } ) export {pokemonsReducer, handleSetPokemons}
El resto está igual a como fue realizado en la clase.