React Context API
En esta sección aprenderemos a trabajar con Context API.
⭐ Videos Premium ⭐
Esta sección es parte del curso en Udemy. Si quieres acceder a ella, puedes comprar el curso en Udemy: React + Firebase by bluuweb.
Proyecto Final
WARNING
Es necesario ver la sección anterior donde trabajamos con React Router Dom v6.
Contex API
- contex API
- Hook useContext
- Context provee una forma de pasar datos a través del árbol de componentes sin tener que pasar props manualmente en cada nivel.
- Context está diseñado para compartir datos que pueden considerarse “globales” para un árbol de componentes en React, como el usuario autenticado actual, el tema o el idioma preferido.
- Si trabajas con diferentes vistas estas no estarán anidadas, por ende Context proporciona una solución.
Redux vs Context
- Redux proporciona un conjunto de herramientas completo para administrar el estado:
- Viene con un depurador que viaja en el tiempo.
- Proporciona una API de middleware que le brinda acceso a herramientas como redux-sagas.
- Sus enlaces de React evitan muchos renderizados innecesarios.
Como puede ver, el contexto no reemplaza a Redux. El contexto no le permitirá viajar en el tiempo con depuración, middleware configurable.
Context es una forma de obtener datos de un lugar a otro. Si desea una herramienta que lo ayude a administrar su estado, Redux es una excelente opción.
Template Base
npm create vite@latest .
npm install
npm install react-router-dom@6.4
CreateContext
- CreateContext
- useContext
- Crea un objeto Context. Cuando React renderiza un componente que se suscribe a este objeto Context, este leerá el valor de contexto actual del Provider más cercano en el árbol.
- Cada objeto Context viene con un componente Provider de React que permite que los componentes que lo consumen se suscriban a los cambios del contexto.
- El componente Provider acepta una prop value que se pasará a los componentes consumidores que son descendientes de este Provider.
context/UserContext.jsx
import { createContext, useContext } from "react";
export const UserContext = createContext(false);
export const useUserContext = () => useContext(UserContext);
components/Navbar.js
import { NavLink } from "react-router-dom";
import { useUserContext } from "../context/UserContext";
const Navbar = () => {
console.log(useUserContext());
return (
<nav>
<NavLink to="/">Home</NavLink>
<NavLink to="/dashboard">Dashboard</NavLink>
</nav>
);
};
export default Navbar;
Provider
- Provider
- Cada objeto Context viene con un componente Provider de React que permite que los componentes que lo consumen se suscriban a los cambios del contexto.
- El componente Provider acepta una prop value que se pasará a los componentes consumidores que son descendientes de este Provider.
context/UserContext.jsx
import { createContext, useContext, useState } from "react";
export const UserContext = createContext();
const UserProvider = ({ children }) => {
const [user, setUser] = useState(null);
return (
<UserContext.Provider value={{ user, setUser }}>
{children}
</UserContext.Provider>
);
};
export default UserProvider;
export const useUserContext = () => useContext(UserContext);
main.jsx
import UserProvider from "./context/UserContext";
ReactDOM.createRoot(document.getElementById("root")).render(
<React.StrictMode>
<UserProvider>
<RouterProvider router={router} />
</UserProvider>
</React.StrictMode>
);
Navbar.jsx
import { NavLink } from "react-router-dom";
import { useUserContext } from "../context/UserContext";
const Navbar = () => {
const { user, setUser } = useUserContext();
return (
<nav>
<NavLink to="/">Home</NavLink>
{user && (
<>
<NavLink to="/dashboard">Dashboard</NavLink>
<button onClick={() => setUser(null)}>Logout</button>
</>
)}
</nav>
);
};
export default Navbar;
Home.jsx
import { useUserContext } from "../context/UserContext";
const Home = () => {
const { user, setUser } = useUserContext();
return (
<>
<h1>Home</h1>
{!user && (
<button onClick={() => setUser({ name: "John Doe" })}>Login</button>
)}
</>
);
};
export default Home;
Private Rutes
Las rutas protegidas son rutas que solo se pueden acceder si el usuario está autenticado. Si el usuario no está autenticado, se redirige a la página de inicio de sesión.
LayoutPrivate.jsx
import { useEffect } from "react";
import { Outlet, useNavigate } from "react-router-dom";
import { useUserContext } from "../context/UserContext";
const LayoutPrivate = () => {
const { user } = useUserContext();
const navigate = useNavigate();
useEffect(() => {
if (!user) {
navigate("/");
}
}, [user]);
return <Outlet />;
};
export default LayoutPrivate;
Alternativa Navigate
import { Outlet, Navigate } from "react-router-dom";
import { useUserContext } from "../context/UserContext";
const LayoutPrivate = () => {
const { user } = useUserContext();
return <>{user ? <Outlet /> : <Navigate to="/" />}</>;
};
export default LayoutPrivate;
Dashboard.jsx
import { useUserContext } from "../context/UserContext";
const Dashboard = () => {
const { user } = useUserContext();
return (
<>
<h1>Dashboard</h1>
<p>{user?.name}</p>
</>
);
};
export default Dashboard;
Home.jsx
import { useNavigate } from "react-router-dom";
import { useUserContext } from "../context/UserContext";
const Home = () => {
const { user, setUser } = useUserContext();
const navigate = useNavigate();
const handleClickLogin = () => {
setUser({ name: "John Doe" });
navigate("/dashboard");
};
return (
<>
<h1>Home</h1>
{!user && <button onClick={handleClickLogin}>Login</button>}
</>
);
};
export default Home;