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.
Conceptos claves para empezar
¿Ya tomaste el Curso Básico de Redux?
Conceptos claves de Redux
Ciclo de vida de Redux
Diferencias entre Redux y Context
Introducción a nuestro proyecto
Creemos una Pokedux
Iniciando nuestro proyecto
¡Atraparlos ya!
Introducción a PokeAPI
React.js + Redux
Integrando Redux
Hooks vs. Connect
Redux DevTools
Middlewares
Middlewares
Peticiones asíncronas
Redux Thunk
Middlewares alternativos: Redux Saga
Avanzando la ui
Agreguemos un loader
Agreguemos favoritos
Inmutabilidad
¿Qué es inmutabilidad?
Agregando Inmutabilidad a nuestra Pokedux
Avanzado
Cuándo usar reducers combinados
Redux Toolkit: creando nuestro primer Slice
Redux Toolkit: createAsyncThunk
Despedida del curso
Conclusiones
No tienes acceso a esta clase
¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera
Mariangélica Useche
Aportes 9
Preguntas 4
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.
Se supone que JS fuera mas fácil pero veo que cada vez se vuelve mas y mas difícil de entender
que triste
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
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;
}
};
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;
shallowEqual
vs. Comparación a Profundidad
en JavaScriptSupongamos 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.
¿Quieres ver más aportes, preguntas y respuestas de la comunidad?