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?

o inicia sesi贸n.

En rootReducer.js, recuerden importar lo siguiente:

import { combineReducers } from 鈥渞edux-immutable鈥, desde redux-immutable.

Si importan combineReducers from 鈥渞edux鈥, les va a arrojar error y perder谩n 15 minutos de sus vidas.

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

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 ```

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

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.

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.

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

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;