No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Cuándo usar reducers combinados

19/22
Recursos

Aportes 9

Preguntas 4

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

En rootReducer.js, recuerden importar lo siguiente:

import { combineReducers } from “redux-immutable”, desde redux-immutable.

Si importan combineReducers from “redux”, les va a arrojar error y perderán 15 minutos de sus vidas.

A día de hoy lunes 30 del 2023 hay un conflicto entre `immutable.js` y `redux-immutable` para toda otra persona que lo este viendo por estas fechas, estos son los repositorios de <https://github.com/immutable-js/immutable-js/> y <https://www.npmjs.com/package/redux-immutable> respectivamente, para resolver el conflicto (Si aún no está parcheado) solo hay que hacer un downgrade del paquete `immutable.js` (Qué es lo que recomienda el CLI de npm para este caso). De modo que tendrías que hacer lo siguiente: ```js npm i immutable@4 redux-immutable ```

Se supone que JS fuera mas fácil pero veo que cada vez se vuelve mas y mas difícil de entender
que triste

Avanzado

Cuándo usar reducers combinados

Combinar reducers es opcional y puede mejorar la experiencia de desarrollo. Sin embargo, eres libre de manejar todo con 1 solo reducer (aunque no es recomendable).

Usaremos redux-immutable

Reducers Combinados

primero se crea una carpeta de reducer, en esa creamos el archivo index o la raiz de todos los reducer combinados

reducer independientes


//pokemons.jsx
import { SET_ERROR, SET_POKEMONS, SET_FAVORITE } from "../actions/types";
import { fromJS, get, setIn } from "immutable";
const initialState = fromJS({
  pokemons: [],
  loading: true,
});
export const pokemonsReducer = (state = initialState, action) => {
  switch (action.type) {
    case SET_POKEMONS:
      const pokemonsUpdated = setIn(
        state,
        ["pokemons"],
        fromJS(action.payload)
      );
      return pokemonsUpdated.set(["loading"], false);

    case SET_FAVORITE:
      const pokemonFoundIndex = get(state, "pokemons").findIndex((pkm) => {
        const pkmon = pkm.toJS().id;
        return pkmon == action.payload.id;
      });
      console.log(pokemonFoundIndex, action.payload.id);

      if (pokemonFoundIndex < 0) return state;

      const isFavorite = get(state, [
        "pokemons",
        pokemonFoundIndex,
        "isFavorite",
      ]);
      return setIn(
        state,
        ["pokemons", pokemonFoundIndex, "isFavorite"],
        !isFavorite
      );
    default:
      return state;
  }
};

//iu.jsx

import { SET_ERROR, SET_POKEMONS,SET_FAVORITE } from "../actions/types";
import {fromJS, get, set, setIn} from 'immutable'
const initialState = fromJS({
  error:false
});
export const uiReducer = (state = initialState, action) => {
  switch (action.type) {
    case SET_ERROR: 
    return state.set(['error'],action.payload);
    default:
      return state;
  }
};

// const

IndexReducers o el rootReducer

import {combineReducers} from 'redux-immutable';
import { uiReducer } from './iu';
import { pokemonsReducer } from './pokemons';
//como estamos utilicemmos la libreria de immutable, para 
// usar reducer combinados, necesitamos instalar redux-immutable
const rootReducer= combineReducers({
    data:pokemonsReducer,
    ui: uiReducer
})
export default rootReducer;

ahora pasamos al index de nuestra app y mandamos el reducer que combina el resto

import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import { Provider } from "react-redux";
import thunk from 'redux-thunk'
import { applyMiddleware, compose, legacy_createStore as createStore } from "redux";
import { loger } from "./middlewares";
import rootReducer from "./reducers/rootReducer";

const composeAlt = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const componoseEnjencer = composeAlt(applyMiddleware(thunk,loger));

		

const store = createStore(rootReducer,componoseEnjencer);

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

como estamos usando immutable js necesitamos reacomodar en donde utilizamos nuestro estado

import { Searched } from "./components/Searched";
import { shallowEqual, useDispatch, useSelector } from "react-redux";
import { Col, Row } from "antd";
import "./App.css";
import { getPokemonWithDetails, setPokemons } from "./actions";
import { PokemonList } from "./components/PokemonList";
// import { usePokeApi } from './hooks/usePokeApi';
import { PokeSkeleton } from "./components/PokeSkeleton";
import { useEffect } from "react";
import { getPokemonDetails, getPokemons } from "./services/PokeApi";
import { get } from "immutable";

function App() {
  const state = useSelector((state) => state.get('data',shallowEqual).toJS());
  //la funcion shadow equal ayuda a verificar si el estado ha cambiado
  // y si no cambio no hara render innecesarios, es decir, no hara rerender
  
  const dispatch = useDispatch();
  const {  pokemons,loading} = state
  useEffect(() => {
   getPokemons()
    .then(pkmos=>dispatch(getPokemonWithDetails(pkmos.results)))
    .catch(err=>console.log(err));
  }, []);
  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>
  );
}

export default App;

Uso de shallowEqual vs. Comparación a Profundidad en JavaScript

Supongamos que tenemos dos objetos de Pokémon:

const pokemon1 = { nombre: "Pikachu", tipo: "Eléctrico" };
const pokemon2 = { nombre: "Pikachu", tipo: "Eléctrico" };

Ahora, si utilizamos shallowEqual para compararlos:

import { shallowEqual } from 'react-redux';

console.log(shallowEqual(pokemon1, pokemon2)); // true

En este caso, shallowEqual compara las propiedades de nivel superior de los objetos pokemon1 y pokemon2, que son nombre y tipo. Como ambas propiedades tienen los mismos valores, la comparación devuelve true.

Sin embargo, si comparamos los mismos objetos directamente con una comparación a profundidad utilizando el operador ===:

console.log(pokemon1 === pokemon2); // false

La comparación a profundidad verifica si los objetos son idénticos en estructura y valor, incluyendo todas las propiedades anidadas. A pesar de que las propiedades nombre y tipo tienen los mismos valores en ambos objetos, la comparación a profundidad devuelve false porque los objetos en sí no son idénticos en estructura. son dos objetos diferentes
.
shallowEqual es útil cuando solo necesitas comparar las propiedades de nivel superior de objetos, evitando renders innecesarios en componentes de React al utilizar Redux. Si necesitas comparar objetos en su totalidad, incluyendo propiedades anidadas, una comparación a profundidad es necesaria.

npm install redux-immutable

Es más una reflexión según lo que entendí de esta clase…

Antes en la clase 18 cuando usamos por primera vez la librería immutable, también debimos usar el shallowEqual debido a que estamos regresando una referencia distinta cada vez que consultamos el estado con useSelector ya que si el estado cambiaba o no cambiaba, la referencia es siempre distinta. Sin immutable no había problema porque a pesar de regresar referencias distintas Redux aquí compara valores, no referencias.
Por supuesto, sin immutable habría que desestructurar los niveles de profundidad que pudieran existir en alguna de las propiedades de nuestro estado.

ShallowEqual: Evalua la diferencia de un objeto en su version anterior y actual para evitar el rerendering.