No tienes acceso a esta clase

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

Hooks vs. Connect

9/22
Recursos

Aportes 19

Preguntas 4

Ordenar por:

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

o inicia sesi贸n.

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.

Redux en lo salvaje



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.

Si a alguien se le dificulta un poco entender el concepto general de la forma de trabajar de Redux (como a mi), les recomiendo ver este corto video:
https://www.youtube.com/watch?v=j-jzI3wkkVk&ab_channel=Fazt

Hooks vs. Connect

useSelector vs Connect

  • Boilerplate -> Los hooks ahorran mucho c贸digo aqu铆.
  • Separaci贸n de responsabilidades -> Connect hace un High Order Component, as铆 que es mejor.
  • Testing -> Es un poco m谩s f谩cil con Connect.

Redux ahora recomienda usar su Hooks API. - Redux Docs

Use the React-Redux Hooks API

  • useSelector -> const list = useSelector(state => state.list);
  • useDispatch -> const dispatch = useDispatch(); dispatch(myAction());

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
    }

}

9.-Hooks vs. Connect


useSelector vs Connect

  • Boilerplate: Nos ahorramos codigo usando hooks.
  • Separaci贸n de responsabilidades: Connect el metodo crea un componente de orden mayor que es quien renderiza el componente y le pasa el estado y action a trav茅s de los props.
  • Testing: Es m谩s f谩cil hacer testing con connect ya que recibe el estado por los props y solo se env铆an props, en cambio con los hooks tendremos que conectar el componente a redux antes de testear.


Redux recomienda usar su Hooks API.


Hooks API

  • useSelector: nos permite extraer la data del estado a traves de una funcion selectora (que debe ser pura), es equivalente al mapstatetoprops, solo que el valor se guarda en una variable. El selector sera llamado cada que se haga distpatch de una acci贸n para evaluar si se renderiza de nuevo un componente.
  • useDispatch: nos retorna una referencia del dispatcher del store de redux el cual usamos para disparar acciones.

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 鈥淗ook鈥:
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 鈥淐onnect鈥:

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

* useSelector `const list = useSelector(state => state.list)` * nos permite extraer la data del estado atraves de una funcion selectora (las funcion es pura), es equivalente al `mapstatetoprops`, solo que el valor se guarda en una variable. el selector ser谩 llamado cada que se haga **distpatch** de una accion para evaluar si se renderiza de nuevo un componente * 馃挕 `useSelector` es semejante a `state` de `const [state, setState] = useState()` osea que podemos sacar datos de hay solo que tenemos que especificar de donde los queremos sacar o de que parte del **reducer** lo queremos sacar el **state** o los datos. la maquina osea `useSelector` entiende automaticamente de donde va a sacar el **state** del **reducer** tan solo tenemos que especificarlo como `const pokemons = useSelector((state) => state.pokemons)` que le estamos sacando los datos de la API * \------------------------------------------ * useDispatch `const dispatch = useDispatch()` `dispatch(myAction())` * nos retorna una referencia del **distpatch** del Store de Redux el cual usamos para disparar acciones * 馃挕 `const dispatch = useDispatch()` `dispatch(myAction())` es semejante al `setState` de `const [state, setState] = useState()` osa que podemos enviar cualquier datos al **action** de los objetos `dispatch(setLoading(true))` que anteriormente hicimos y cuando el objeto retorne sus valores como el `type` y el `payload` le lo estaremos enviando al **store** de Redux y el **store** selo enviara al **action** y este lo actualizara los **state** indicados, que posteriormente los llamaremos con `useSelector`
* useSelector `const list = useSelector(state => state.list)` * * nos permite extraer la data del estado atraves de una funcion selectora (las funcion es pura), es equivalente al `mapstatetoprops`, solo que el valor se guarda en una variable. el selector ser谩 llamado cada que se haga **distpatch** de una accion para evaluar si se renderiza de nuevo un componente * \<aside> 馃挕 `useSelector` es semejante a `state` de `const [state, setState] = useState()` osea que podemos sacar datos de hay solo que tenemos que especificar de donde los queremos sacar o de que parte del **reducer** lo queremos sacar el **state** o los datos. la maquina osea `useSelector` entiende automaticamente de donde va a sacar el **state** del **reducer** tan solo tenemos que especificarlo como `const pokemons = useSelector((state) => state.pokemons)` que le estamos sacando los datos de la API\</aside>
| hola mundo
como save que "action" es SET\_POKEMONS como save que "const pokemons = useSelector((state) => state.pokemons)" esta tomando el array de los pokemons y no otra cosa
el codigo se volvio mucho mas legible, a buena hora implementaron lo de los hooks

Esta profesora es realmente muy buena, puede llegar a hacerte entender Redux en muy poco tiempo.

App.jsx

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;