Muchísimo mejor con hooks…
Conceptos claves para empezar
Ciclo de Vida en Redux y Creación de Middleware Personalizado
Conceptos Clave de Redux para Manejo de Estado
Ciclo de Vida del Estado en Redux para Aplicaciones React
Diferencias entre Redux y Context API en React
Introducción a nuestro proyecto
Integración de Redux en Aplicaciones React
Maquetación web con React y Ant Design: Componentes y Estilos
¡Atraparlos ya!
Integración de APIs REST en JavaScript con Axios
React.js + Redux
Integración de Redux en React: Uso de Connect y Reducers
Uso de Hooks en React Redux: useSelector y useDispatch
Instalación y uso de Redux DevTools en navegadores
Middlewares
Creación de Middleware Personalizado en Redux
Obteniendo Imágenes de Pokémon con PokeAPI y JavaScript
Programación asíncrona con Redux y Tonk
Diferencias Clave: Redux Thunk vs Redux Saga
Avanzando la ui
Spinner y Estado de Carga en Aplicaciones React
Mapeo y Renderizado de Tipos en Tarjetas de Pokémon
Inmutabilidad
Inmutabilidad en JavaScript: Objetos y Spread Operator
Implementación práctica de inmutabilidad con ImmutableJS
Avanzado
Arquitectura de Reducers con Redux: Organiza tu Estado de Forma Eficaz
Redux Toolkit: Simplifica tu Gestión de Estado en JavaScript
Asincronismo con Redux Toolkit: CreateAsyncThunk y UI Slice
Despedida del curso
Estado Global con Redux en Aplicaciones JavaScript
No tienes acceso a esta clase
¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera
Conectar un componente a Redux puede simplificar considerablemente el código gracias al uso de hooks. Anteriormente, se utilizaba el método connect
, que involucraba la creación de mapas de estado y despachos a propiedades (mapStateToProps y mapDispatchToProps), así como un envoltorio de nuestro componente. Ahora, usando hooks, podemos lograr el mismo resultado con solo dos líneas de código.
El uso del método connect
requiere más código porque implica lo siguiente:
mapStateToProps
y mapDispatchToProps
.En cambio, los hooks ofrecen las siguientes ventajas:
Redux ofrece dos hooks esenciales para manejar el estado:
useSelector: Extrae la data del estado mediante una función selectora pura que suscribe el componente al estado. Se llama cada vez que se produce una acción que puede cambiar el valor, permitiendo rerenderizar el componente según sea necesario.
useDispatch: Retorna una referencia al dispatcher de Redux, utilizado para disparar acciones.
Implementar hooks en un proyecto que previamente usaba connect
se puede lograr siguiendo estos pasos:
Limpieza de Código:
mapStateToProps
y mapDispatchToProps
.Implementación de Hooks:
useSelector
y useDispatch
desde React Redux.useSelector
para acceder y guardar el estado necesario en una variable.useDispatch
para obtener el dispatcher y gestionar acciones.import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { setPokemon } from './actions';
const PokemonComponent = () => {
const pokemonList = useSelector(state => state.pokemonList);
const dispatch = useDispatch();
const handleSetPokemon = () => {
dispatch(setPokemon());
};
return (
<div>
{pokemonList.map(pokemon => (
<div key={pokemon.id}>{pokemon.name}</div>
))}
<button onClick={handleSetPokemon}>Set Pokémon</button>
</div>
);
};
export default PokemonComponent;
Con este enfoque, puedes ver cómo se mantiene la funcionalidad original con una notable reducción de código y una experiencia de desarrollo más intuitiva. Sin duda, los hooks son una poderosa herramienta que redefine la forma en que interactuamos con Redux, animándote a adoptarlos en futuros proyectos.
Aportes 19
Preguntas 4
Muchísimo mejor con hooks…
Soy un viejo usuario de Redux. Hoy en dia uso solo los hooks. Me gusta mucho mas y para testear no se me complico tanto. Simplemente mockeo al estado actual y listo.
Aparte del titulo de periodico que coloque, mi experiencia con Redux es que muchos proyectos utilizan el connect API para sus componentes.
Esto no solo se debe a que muchas veces se trata de proyectos comenzados antes de la existencia de los Hooks, sino tambien a una question de consistencia. Tanto a nivel de testing como menciono la profesora, como a nivel de desarrollo del codigo en general.
Personalmente veo mucho mas facil e intuitivo utilizar Hooks y componentes funcionales. Pero es bueno que conozcas las maneras “legacy” porque te lo vas a encontrar mucho en el ambito laboral.
useSelector vs Connect
Redux ahora recomienda usar su Hooks API. - Redux Docs
const list = useSelector(state => state.list);
const dispatch = useDispatch(); dispatch(myAction());
–
useSelector vs Connect
–
Redux recomienda usar su Hooks API.
–
Hooks API
Dejo mi avance en TS:
// App.tsx
import { useEffect, useState } from 'react'
import { connect, useDispatch, useSelector } 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 { setPokemons } from './actions'
import { TypeState } from './reducers/pokemon'
function App() {
const pokemons = useSelector((state:TypeState)=>state.pokemons)
const dispath = useDispatch();
useEffect(()=>{
async function fetchPokemon(){
const pkmns = await getPokemons();
dispath(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>
)
}
export default App;
// pokemon.ts
import { SET_POKEMONS } from "../actions/types"
import { PokemonType } from "../api"
export 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
}
}
Comencé el proyecto con TypeScript y acá tiro el resumen:
// ** index.tsx
// Acá de crea el store.
// Por medio del provider de redux se pasa el reducer, que contiene el state
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 root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
);
const store = createStore(pokemonsReducer);
root.render(
<Provider store={store}>
<React.StrictMode>
<App />
</React.StrictMode>
</Provider>
);
·
//** reducers/pokemons.ts
// Acá se inicializa el state.
// Creamos la función reducer: función que recibe *el state* y *el action*.
// El action contiene: el type del action y el payload.
// Se evalúa el type del action, para devolver el state correcto con lo que contine el payload.
import { PokemonType } from "../api";
import { SET_POKEMONS } from "../actions/types";
type InitialPokemonsStateType = {
pokemons: PokemonType[]
};
const initialState: InitialPokemonsStateType = {
pokemons: []
}
export const pokemonsReducer = (
state: InitialPokemonsStateType = initialState,
action: any
) => {
switch(action.type) {
case SET_POKEMONS:
return {
...state,
pokemons: action.payload,
};
default: return state;
}
};
·
// ** actions/index.ts
// El action es una función que recibe un payload.
// Devuelve un objeto con el type y el payload que recibe.
import { PokemonType } from "../api";
import { SET_POKEMONS } from "./types";
export const setPokemons = (payload: PokemonType) => ({
type: SET_POKEMONS,
payload,
});}
// actions/type.ts
export const SET_POKEMONS = 'SET_POKEMONS';
·
// ** api/index.ts
// Acá se crea el llamado a la API y los tipados globales.
import axios from "axios"
export type PokemonType = {
name: string;
url: string;
};
export type PokemonResponse = {
results: PokemonType[];
}
const getPokemon = async () => {
const URL = 'https://pokeapi.co/api/v2/pokemon?limit=151';
try {
const { data: { results } } = await axios.get(URL);
return results;
} catch (err) {
console.error('err '.repeat(5), err);
}
}
export default getPokemon;
·
//** App.tsx
// Acá suscribimos el componente al state con useSelector
// También se dispara la acción con useDispatch para que llame los pokemons y se ejecute el reducer
// El reducer actualiza el estado global de la aplicación
import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Col } from 'antd';
import Searcher from './components/Searcher';
import PokemonList from './components/PokemonList';
import getPokemon, { PokemonType } from './api';
import { setPokemons } from './actions'
import logo from './statics/logo.svg';
import './App.css';
type AppType = {
pokemons: PokemonType[],
setPokemons: any,
}
function App() {
const pokemons = useSelector((state: AppType) => state.pokemons);
const dispatch = useDispatch()
useEffect(() => {
const fetchPokemons = async () => {
const response = await getPokemon();
dispatch(setPokemons(response));
}
fetchPokemons();
}, []);
console.log('pokemons ', pokemons)
return (
<div className='App'>
<Col span={4} offset={10}>
<img src={logo} alt='Pokedux'/>
</Col>
<Col span={8} offset={8}>
<Searcher />
</Col>
<PokemonList results={pokemons} />
</div>
);
}
export default App;
Ventajas de “Hook”:
Permite una escritura más limpia y sencilla de los componentes de React.
Facilita la reutilización de código y la composición de funcionalidades.
Mejora la legibilidad del código al separar la lógica de los componentes de React.
Ventajas de “Connect”:
Ofrece una forma centralizada y eficiente de gestionar el estado global de la aplicación.
Facilita la implementación de patrones de diseño como la arquitectura Flux.
Mejora la escalabilidad de la aplicación al mantener una única fuente de verdad para el estado.
Amo los hooks, además sigue la misma forma de trabajar el traspaso de información con react que en los cursos anteriores.
si se ejecuta dispactch de la accion se renderiza de nuevo el selector
Esta profesora es realmente muy buena, puede llegar a hacerte entender Redux en muy poco tiempo.
import {Col} from 'antd';
import Searcher from "./components/Searcher";
import {useEffect} from 'react'
import PokemonList from "./components/PokemonList.jsx";
import {getPokemon} from "./api";
import {setPokemons} from "./actions/index.js";
import Logo from "./assets/logo.svg";
import './App.css'
import {useDispatch, useSelector} from "react-redux";
function App() {
const pokemons = useSelector(state => state.pokemons);
const dispatch = useDispatch();
useEffect(() => {
const fetchPokemons = async () => {
const response = await getPokemon();
dispatch(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>
)
}
export default App;
¿Quieres ver más aportes, preguntas y respuestas de la comunidad?