Al principio dudaba de la diferencia de ambos al haber usado Redux, el cual usa un Unico Store para almacenar los stados de la aplicacion y por medio de acciones( enviadas al interactuar con la UI de la App) estas se filtran por tipo y el reducer (funccion que trabaja sobre el Store) toma el nuevo estado que manda la accion y actualiza el Store el cual por medio del Provider (etiqueta JSX que engloba a un conjunto de componentes para que estos esten vinculados al Store) se muestran los cambios en la UI. Un ejemploe es el tipico agregar a favoritos.
Pues bueno, la parecer useContext y useReducer manejan ciertos aspectos por separado que Redux manejaba conjuntamente. El Context seria el store global y el useReducer un Store local para el componente en cuestion, aparte de esta diferencia es el uso de funciones pues useReducer si que emplea el conjunto accion -> reducer ->store
documentacion oficial
Se utiliza para mantener estados globales como temas, idiomas de la aplicación o datos del usuario. En primer lugar, inicializamos el Contexto, una variable que contiene React.createContext, este sera el almacen. Ahora el Provider envuelve a los componentes hijo que tendran acceso al almacen, con la etiqueta <MyContext.provider value=""/>. Así que ahora podemos acceder a propiedades del almacen desde el componente a través de useContext (MyContext) y aplicar las propiedades deseadas.
const themes = {
light: {
foreground: "#000000",
background: "#eeeeee"
},
dark: {
foreground: "#ffffff",
background: "#222222"
}
};
const ThemeContext = React.createContext(themes.light);
functionApp() {
return (
<ThemeContext.Provider value={themes.dark}>
<Toolbar />
</ThemeContext.Provider>
);
}
function Toolbar(props) {
return (
<div>
<ThemedButton />
</div>
);
}
function ThemedButton() {
const theme = useContext(ThemeContext); return ( <button style={{ background: theme.background, color: theme.foreground }}> I am styled by theme context! </button> );
}
Ahora en lugar de tener una almacen global contamos con uno local para el componente, se usa cuando la complejidad del componente aumenta y useState se queda corto. En primer lugar, inicializamos un objeto de estado a través de una función o manualmente, initialState. Después, creamos la función reducer cuyos parámetros serán el estado actual del componente y la acción enviada por el cliente. En el interior a través de un switch como filtro se especificará la acción solicitada, aplicando los cambios al estado del almacen. Ahora, podemos usar nuestra desestructuración de objetos en dos variables, el estado actualizado y la acción que es el dispacher, esto será igual al useReducer que acepta dos parámetros, la función reducer y el estado inicial.
Finalmente, una función onClick pro ejemplo desencadena esa actualización enviando al dispacher junto con el estado para ser filtrado por el reducer sobreescribinedo el estado del almacen.
const initialState = {count: 0};
function reducer(state, action) {
switch (action.type) {
case 'increment':
return {count: state.count + 1};
case 'decrement':
return {count: state.count - 1};
default:
throw new Error();
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<>
Count: {state.count}
<button onClick={() => dispatch({type: 'decrement'})}>-</button><button onClick={() => dispatch({type: 'increment'})}>+</button></>
);
}