No tienes acceso a esta clase

隆Contin煤a aprendiendo! 脷nete y comienza a potenciar tu carrera

useAuth: login y logout

11/30
Recursos

Aportes 19

Preguntas 3

Ordenar por:

驴Quieres ver m谩s aportes, preguntas y respuestas de la comunidad?

useAuth: login y logout

Ahora vamos a aprender como desplegar contenido en base a la Autenticaci贸n de usuarios, 贸sea que no todo el contenido de una aplicaci贸n va a ser p煤blico pata todos los usuarios, sino que tengamos algunas rutas privadas para personas que no se hayan autenticado, 贸sea hecho login y as铆 mismo no mostrar contenido que es innecesario para personas que ya est谩n registradas, como el mismo registro de usuario o contenido introductorio.

Vamos a hacer contenido que dependiendo el usuario se muestre o no se muestre, y tambi茅n permitir tener privilegios o permisos dependiendo del rol que tengas.

Vamos entonces a crear nuevas rutas que nos permitan hacer todo esto:

import { LoginPage } from './Components/Routes/LoginPage/LoginPage';
import { LogoutPage } from './Components/Routes/LogoutPage/LogoutPage';

function App() {
  return (
    <>
      <HashRouter>
				<Routes>
	        ...
          
          <Route path='/login' element={<LoginPage />} /> 
          <Route path='/logout' element={<LogoutPage />} />
          <Route path='/profile' element={<ProfilePage />} />

        </Routes>
      </HashRouter>
    </>
  )
}

Y debemos crear nuestros respectivos componentes:

LoginPage.js

import React from 'react';

function LoginPage() {
  /* Para manejar el registro de usuario con el formilario haremos 
  uso del estado de React */
  const [username, setUsername] = React.useState('');

  /* Esta es la funci贸n que se ejecutar谩 cuando ocurra el evento de 
  Submit */
  const login = (e) => {
    e.preventDefault();
  }

  // Aqu铆 creamos un formulario para poder auteticarnos
  return (
    <>
      <h1>Login</h1>

      <form onSubmit={login}>
        <label>Escribe tu nombre de usuario</label>
        <input
          value={username}
          onChange={ e => setUsername(e.target.value)}
        />

        <button type="submit">Entrar</button>

      </form>
    </>
  );
}

export { LoginPage }

LogoutPage.js

import React from 'react';

function LogoutPage() {
  const logout = (e) => {
    e.preventDefault();
  }

  return (
    <>
      <h1>Logout</h1>

      <form onSubmit={logout}>
        <label>驴Segurx de que quieres salir?</label>

        <button type="submit">Salir</button>

      </form>
    </>
  );
}

export { LogoutPage }

En nuestro Menu.js vamos a crear dos nuevas rutas en nuestro Array routes:

...
const routes = [];

...
routes.push({
  to: '/login',
  text: 'Logout'
});
routes.push({
  to: '/logout',
  text: 'Login'
});

Si lo pensamos bien, no nos deber铆a salir el componente Profile y Logout sin antes haber hecho un Login, vamos a trabajar entonces en esa l贸gica creando un archivo de autenticaci贸n:

auth.js

import React from 'react';

const AuthContext = React.createContext();

function AuthProvider({ children }) {
  const auth = {
    user,
    login,
    logout,
  }

  return (
    <AuthContext.Provider
      value={auth}
    >
      {children}
    </AuthContext.Provider>
  )
}

function useAuth() {
  const auth = React.useContext(AuthContext);
  return auth;
}

export {
  AuthProvider,
  useAuth,
}

Vamos a importar esta l贸gica al App.js:

...
import { AuthProvider, useAuth } from './Components/auth/auth'

function App() {
  return (
    <>
      {/* En este caso AuthProvider tiene que ir dentro de 
      HastRouter en caso de que AuthProvider necesite de alg煤n 
      m茅todo o contenido que pueda proveer HashRouter */}
      <HashRouter>
        <AuthProvider>
          <Menu />

          <Routes>
            <Route path='/' element={<HomePage />} />
            <Route path='/blog' element={<BlogPage />}>
              <Route path=':slug' element={<BlogPost />} />
            </Route>
            
            <Route path='/login' element={<LoginPage />} />
            <Route path='/logout' element={<LogoutPage />} />
            <Route path='/profile' element={<ProfilePage />} />

            <Route path='/*' element={<p>Not Found</p>} />

          </Routes>
        </AuthProvider>

      </HashRouter>
    </>
  )
}

...

En este punto, en LoginPage.js ya podemos empezar a utilizar nuestro useAuth:

import { useAuth } from '../../auth/auth';
...

function LoginPage() {
  const auth = useAuth();
	...
}

Vamos de nuevo auth.js y seguimos con la l贸gica:

...
function AuthProvider({ children }) {
  /* Siguiendo la l贸gica, si user es null significa que no estamos 
  autenticados */
  const [user, setUser] = React.useState(null);

  // Ahora necesitamos darle un valor a nuestro usuario
  const login = ({ username }) => {
    setUser({ username });
  }

  // De la misma forma, debemos poder cerrar la sesi贸n
  const logout = () => {
    setUser(null);
  }
	...
}

Ahora en LoginPage.js nuestro useAuth nos debe dar acceso al usuario y sus m茅todos:

function LoginPage() {
  const login = (e) => {
    e.preventDefault();
    auth.login({ username })
  }
}

Vamos de nuevo a auth.js y vamos a complementar la l贸gica:

function AuthProvider({ children }) {
  const navigate = useNavigate();

  const login = ({ username }) => {
    setUser({ username });
		/* Ahora cada vez que hagamos login nos redireccionar谩 a la 
		p谩gina de profile */
    navigate('/profile');
  }

  const logout = () => {
		setUser(null);
    /* Aqu铆 haremos redirect a la p谩gina principal */
    navigate('/');
  }

Pero para esto debemos a帽adir el contexto de autentificaci贸n a LogoutPage.js:

function LogoutPage() {
  const auth = useAuth();

  const logout = (e) => {
    e.preventDefault();
    auth.logout();
  }
}

Ahora en nuestra ProfilePage.js debemos completar esta l贸gica:

import { useAuth } from '../../auth/auth';

function ProfilePage() {
  const auth = useAuth();

  return (
    /* Ahora si nosotros nos registramos deber铆amos poder ver 
		nuestro nombre de usuario en nuestra p谩gina de perfil */
    <>
      <h1>Perfil</h1>
      <h1>Welcome {auth.user.username}</h1>
    </>
  );
}

Y listo, ahora solo nos queda el que no podamos entrar a profile sino hasta que hayamos hecho login, lo cual haremos a continuaci贸n.

Por si alguien tien este error: usando Vite

[vite] Internal server error: Failed to parse source for import analysis because the content contains invalid JS syntax. If you are using JSX, make sure to name the file with the .jsx or .tsx extension.
  Plugin: vite:import-analysis
  File: /home/naiper/cursos/33-react-router/src/helpers/auth.js
  33 |      logout
  34 |    };
  35 |    return <AuthContext.Provider value={auth}>{children}</AuthContext.Provider>;
     |                                                                                ^
  36 |  }
  37 |
      at formatError (file:///home/naiper/cursos/33-react-router/node_modules/vite/dist/node/chunks/dep-db16f19c.js:40862:46)
      at TransformContext.error (file:///home/naiper/cursos/33-react-router/node_modules/vite/dist/node/chunks/dep-db16f19c.js:40858:19)
      at TransformContext.transform (file:///home/naiper/cursos/33-react-router/node_modules/vite/dist/node/chunks/dep-db16f19c.js:37530:22)
      at async Object.transform (file:///home/naiper/cursos/33-react-router/node_modules/vite/dist/node/chunks/dep-db16f19c.js:41111:30)
      at async loadAndTransform (file:///home/naiper/cursos/33-react-router/node_modules/vite/dist/node/chunks/dep-db16f19c.js:37373:29)

Lo que hice fue cambiar el archivo auth.js por un auth.jsx

Otra soluci贸n que encontr茅 fue cambiar la configuraci贸n del vite.config.js

Agregu茅 una regla: 鈥淓nable hmr overlay with vite react and ts鈥

Pero lamentablemente no me sirvi贸, s贸lamente me quit贸 el error en Vite pero me dej贸 en consola.

Decid铆 organizar los archivos de esta manera.

Gracias Juan. De hecho en primera instancia cre铆 que era mejor que el AuthProvider fuera el componente de m谩s arriba. Pero luego de tu explicaci贸n, comprendo qu茅 l贸gica debo tener a la hora de definir c贸mo organizar estos Providers.

Mi Profe Facherito

Cuando relacione el label con el input utilizando for, react me sugiri贸 cambiarlo por htmlFor.

  <label htmlFor='input-login'>Escribe tu nombre de usuario:</label>
        <input
        value={username}
        onChange={e => setUsername(e.target.value)}
        id='input-login'/>

Por si alguien tambi茅n est谩 haciendo el proyecto con TypeScript, comparto c贸mo me qued贸 auth.tsx:

import React, { useContext, useState } from 'react'
import type { PropsWithChildren } from 'react'
import { useNavigate } from 'react-router-dom'

interface Auth {
  user: { username: string } | null
  login: (username: string) => void
  logout: () => void
}

const AuthContext = React.createContext({})

function AuthProvider({ children }: PropsWithChildren) {
  const navigate = useNavigate()
  const [user, setUser] = useState<Auth['user']>(null)

  function login(username: string) {
    if (username) 
      setUser({ username })
      navigate('/profile')
  }
  
  function logout() {
    setUser(null)
    navigate('/')
  }

  const auth: Auth = { user, login, logout }

  return (
    <AuthContext.Provider value={auth}>
      { children }
    </AuthContext.Provider>
  )
}

function useAuth() {
  const authContext = useContext(AuthContext) as Auth
  return authContext
}

export { AuthProvider, useAuth }

Podr铆an verificar que que exista un usuario con:

 <h1>{auth.user?.username}</h1>

el operador 鈥?.鈥 verifica que dentro de objeto auth.user exista username, si no existe devolver谩 undefined y el h1 en la pagina estar谩 vaci贸.
.
o podr铆an hacer una condicional para mostrar un username por default:

const username = auth.user?.username ?? 'User936'

return (
  <h1>{username}</h1>
)

El operador de coalescencia nula ?? solo devuelve el valor del lado derecho (鈥楿ser936鈥) si el valor del lado izquierdo es null o undefined.
Y si no existe un 鈥榰sername鈥 en 鈥榓uth.user?.username鈥 devolver谩 undefined

Esta genial el curso Juan pero m谩s de 20 min de fake auth no me sirve. 馃槮

Esta clase estuvo bien intensa, tuve que mirarla 3 veces para poder entender bien.

C贸digo de TypeScript de la clase:
AuthStore.tsx

import { createContext, FC, useState, PropsWithChildren } from 'react'
import { useNavigate } from 'react-router-dom'

interface User {
    username: string
}

interface Auth {
    user: User | null
    login: (user: User) => void
    logout: () => void
}

// interface Auth {
//     user: { username: string } | null
//     login: (user: Auth['user']) => void
//     logout: () => void
// }

const AuthContext = createContext({} as Auth);

const AuthProvider:FC<PropsWithChildren> = ({ children }) => {

    const navigate = useNavigate();
    const [user, setUser] = useState<Auth['user']>(null);

    const login:Auth['login'] = (user) => {
        setUser(user);
        navigate('/profile')
    }

    const logout:Auth['logout'] = () => {
        setUser(null);
        navigate('/');
    }

    const auth:Auth = { user, login, logout }

    return (
        <AuthContext.Provider value={auth}>
            { children }
        </AuthContext.Provider>
    )
}

export { AuthProvider, AuthContext }

useAuth.ts

import { useContext } from "react"
import { AuthContext } from "./AuthStore"

const useAuth = () => {
    const auth = useContext(AuthContext);
    return auth;
}

export { useAuth }

ProfilePage

import { useAuth } from "./useAuth"

const ProfilePage = () => {

    const { user } = useAuth();

    return(
        <>
            <h1>Perfil</h1>
            <p>Welcome, { user?.username} </p>
        </>
    )
}

export { ProfilePage }

Basicamente lo que hace el metodo 鈥渓ogin鈥 es setear el estado de user name con el nombre de usuario que le pasamos, que viene del input
El metodo 鈥渓ogout鈥 lo que hace es setear ese estado como null
Y todo esta guardado en el contexto al cual tenemos acceso con el hook de useAuth
As铆 lo compartimos con todos los componentes

AuthConsumer pens茅 en OutConsumer uwu, si alguien jugaba NBA en PlayStation all谩 por el a帽o 2012 de repente conoce a ese Youtuber jajaja

useAuth: login y logout

.
Empezamos a desarrollar un flujo de navegaci贸n completo para aplicaciones que tengan autenticaci贸n y autorizaci贸n. Esto significa que no todos los usuarios podr谩n tener acceso a rutas que deber铆an de ser privadas u ocultas si no se han autenticado. Incluso si ya hicieron login hay cosas que no queremos que vean, contenido que no cualquier usuario debe poder ver por cuestiones de autorizaci贸n.
.
Lo primero que haremos en App es crear 2 nuevas rutas /login y logout con sus respectivos componentes a renderizar.
.

<Route path="/login" element={<LoginPage />} />
<Route path="/logout" element={<LogoutPage />} />

.
En Menu tambi茅n a帽adimos estas 2 nuevas rutas al array de rutas.
.

const routes = [];
routes.push({
  to: '/',
  text: 'Home',
});
routes.push({
  to: '/blog',
  text: 'Blog',
});
routes.push({
  to: '/profile',
  text: 'Profile',
});
routes.push({
  to: '/login',
  text: 'Login',
});
routes.push({
  to: '/logout',
  text: 'Logout',
});

.
Vamos a necesitar un archivo auth.js el cual nos va permitir simular nuestro flujo de autenticaci贸n. Su objetivo principal es exportar un objeto que contenga nuestro AuthProvider y nuestro react hook useAuth.
.
En este archivo creamos un contexto para la autenticaci贸n. Dentro del provider de este contexto por medio de la propiedad value le pasamos un objeto auth que va a contener el estado de nuestro usuario user que por defecto es null cuando no est谩 logeado; tambi茅n contiene a las funciones de login y logout que lo que hacen es setear el estado del usuario y navigar como corresponda mediante useNavigate.
.

import React, { useContext } from 'react';
import { useNavigate } from 'react-router-dom';

const AuthContext = React.createContext();

function AuthProvider({ children }) {
  const navigate = useNavigate();
  const [user, setUser] = React.useState(null);

  const login = ({ username }) => {
    setUser({ username });
    navigate('/profile');
  };
  
  const logout = () => {
    setUser(null);
    navigate('/');
  };
  
  const auth = { user, login, logout };

  return (
    <AuthContext.Provider value={auth}>
      {children}
    </AuthContext.Provider>
  );
}

function useAuth() {
  const auth = React.useContext(AuthContext);
  return auth;
}

export {
  AuthProvider,
  useAuth,
};

.
El react hook useAuth lo que hace es simplemente llamar al contexto, guardarlo y exportarlo en una variable.
.
Finalmente, el AuthProvider es un componente que nos permitir谩 encapsular el contenido de nuestro HashRouter en App. Por lo que tendr谩 acceso a la informaci贸n que puede proporcionar HashRouter, pero a la vez los componentes contenidos por AuthProvider como Menu o las rutas, tendr谩n acceso a las propiedades del objeto auth que proporciona el provider.
.

function App() {
  return (
    <>
      <HashRouter>
        <AuthProvider>
          <Menu />

          <Routes>
            <Route path="/" element={<HomePage />} />

            <Route path="/blog" element={<BlogPage />}>
              <Route path=":slug" element={<BlogPost />} />
            </Route>

            <Route path="/login" element={<LoginPage />} />
            <Route path="/logout" element={<LogoutPage />} />
            <Route path="/profile" element={<ProfilePage />} />

            <Route path="*" element={<p>Not found</p>} />
          </Routes>
        </AuthProvider>
      </HashRouter>
    </>
  );
}

.
Posteriormente, creamos o modificamos los componentes necesarios para este flujo, empezando por LoginPage, LogoutPage y Profile.
.
En LoginPage lo que podemos observar es que tenemos un peque帽o formulario que nos permite ingresar el username, y mediante el react hook useAuth al realizar el evento de submit utilizaremos la funci贸n login que a su vez llama a auth.login para setear el valor del nombre de usuario y redirigirnos a la p谩gina de Profile de este.
.

import React from 'react';
import { useAuth } from './auth';

function LoginPage() {
  const auth = useAuth();
  const [username, setUsername] = React.useState('');
  
  const login = (e) => {
    e.preventDefault();
    auth.login({ username });
  };
  
  return (
    <>
      <h1>Login</h1>

      <form onSubmit={login}>
        <label>Escribe tu nombre de usuario:</label>
        <input
          value={username}
          onChange={e => setUsername(e.target.value)}
        />

        <button type="submit">Entrar</button>
      </form>
    </>
  );
}

export { LoginPage };

.
En LogoutPage tambi茅n se tiene un peque帽o formulario que al realizar el evento de submit en este caso va a setear el estado del usuario en null y redirigirnos a la p谩gina principal / por medio del react hook useAuth y la funci贸n logout que a su vez utiliza a auth.logout.
.

import React from 'react';
import { useAuth } from './auth';

function LogoutPage() {
  const auth = useAuth();
  
  const logout = (e) => {
    e.preventDefault();
    auth.logout();
  };
  
  return (
    <>
      <h1>Logout</h1>

      <form onSubmit={logout}>
        <label>驴Segura de que quieras salir?</label>

        <button type="submit">Salir</button>
      </form>
    </>
  );
}

export { LogoutPage };

.
Finalmente para completar esta parte del flujo tenemos a ProfilePage que va renderizar la p谩gina de perfil de usuario. Este utiliza al rect hook useAuth para recuperar la informaci贸n del nombre de usuario y poder renderizarlo.
.
Sin embargo dar谩 error si no se ha pasado a trav茅s de las etapas del flujo adecuadamente. Por lo que a煤n se debe implementar una forma de proteger las rutas para evitar este tipo de error, o condicionar el renderizado de forma que si el usuario es null entonces manejar el renderizado de otra manera.
.

import React from 'react';
import { useAuth } from './auth';

function ProfilePage() {
  const auth = useAuth();
  
  return (
    <>
      <h1>Perfil</h1>
      <p>Welcome, {auth.user.username}</p>
    </>
  );
}

export { ProfilePage };

useAuth: login y logout


  • Definiendo rutas de Login y Logout.

    <Route path="/login" element={<LoginPage />} />
    <Route path="/logout" element={<LogoutPage />} />
    
  • Creando componentes LoginPage y LogoutPage.

    import React from "react";
    
    function LoginPage() {
      return <h1>Login</h1>;
    }
    
    export { LoginPage };
    
    import React from "react";
    
    function LogoutPage() {
      return <h1>Logout</h1>;
    }
    
    export { LogoutPage };
    
  • Agregar Links para login y logout al men煤.

    import React from "react";
    import { NavLink } from "react-router-dom";
    
    function Menu() {
      return (
        <nav>
          <ul>
            {routes.map(route => (
              <li key={route.to}>
                <NavLink 
                  style={({ isActive }) => ({
                    color: isActive ? 'red' : 'blue'
                  })}
                  to={route.to}
                >
                  {route.text}
                </NavLink>
              </li>
            ))}
          </ul>
        </nav>
      )
    }
    
    const routes = [
      { to: '/', text: 'Home' },
      { to: '/blog', text: 'Blog' },
      { to: '/profile', text: 'Profile' }, 
      **{ to: '/login', text: 'Login' },
      { to: '/logout', text: 'Logout' }**
    ];
    
    export { Menu };
    
  • Creando un formulario para el login.

    import React from "react";
    
    function LoginPage() {
      **const [username, setUsername] = React.useState('');
    
      const login = (e) => {
        e.preventDefault();
        console.log(username);
      }**
    
      return (
        <>
          **<h1>Login</h1>
          
          <form onSubmit={login}>
            <label>Escribe tu nombre de usuario:</label>
            <input
              value={username}
              onChange={e => setUsername(e.target.value)}
            />
    
            <button type="submit">Entrar</button>
          </form>**
        </>
      );
    }
    
    export { LoginPage };
    
  • Creando un formulario para logout.

    import React from "react";
    
    function LogoutPage() {
    
      **const logout = (e) => {
        e.preventDefault();
        console.log('Logout');
      }**
    
      return (
        **<>
          <h1>Logout</h1>
    
          <form onSubmit={logout}>
            <label>驴Seguro de que quieres salir?</label>
    
            <button type="submit">Salir</button>
          </form>
        </>**
      );
    }
    
    export { LogoutPage };
    
  • Creamos un provider y un hook para la autentificaci贸n.

    **import React from "react";
    
    const AuthContext = React.createContext()
    
    function AuthPrvider({ children }) {
        const auth = {}
    
        return (
            <AuthContext.Provider value={auth}>
                { children }
            </AuthContext.Provider>
        )
    }
    
    function useAuth() {
        const auth = React.useContext(AuthContext)
        return auth;
    }
    
    export {
        AuthProvider,
        useAuth
    }**
    
  • Implementar el provider en la aplicaci贸n.

    import "./App.css";
    // more imports...
    **import { AuthProvider } from "./api/auth";**
    
    function App() {
      return (
        <>
          <HashRouter>
            **<AuthProvider>**
              <Menu />
    
              <Routes>
                <Route path="/" element={<HomePage />} />
    
                {/* More routes... */}
              </Routes>
            **</AuthProvider>**
          </HashRouter>
        </>
      );
    }
    
    export default App;
    
  • Creamos los m茅todos de login y logout en el provider y lo consumimos en LoginPage y LogoutPage respectivamente.

    ....
    
    const AuthContext = React.createContext()
    
    function AuthProvider({ children }) {
        **const navigate = useNavigate()
        const [user, setUser] = useState()
    
        const login = ({ username }) => {
            setUser({ username })
            navigate('/profile')
        }
    
        const logout = () => {
            setUser(null);
            navigate('/')
        }
    
        const auth = { user, login, logout };**
    
        return (
            <AuthContext.Provider value={auth}>
                { children }
            </AuthContext.Provider>
        )
    }
    
    ...
    
    import React from "react"
    import { useAuth } from "../api/auth"
    
    function LoginPage() {
      **const auth = useAuth()**
      const [username, setUsername] = React.useState('');
    
      const login = (e) => {
        e.preventDefault()
        **auth.login({ username })**
      }
    
      return (
        <>
          <h1>Login</h1>
          
          <form onSubmit={login}>
            <label>Escribe tu nombre de usuario:</label>
            <input
              value={username}
              onChange={e => setUsername(e.target.value)}
            />
    
            <button type="submit">Entrar</button>
          </form>
        </>
      );
    }
    
    export { LoginPage };
    
    import React from "react";
    import { useAuth } from "../api/auth";
    
    function LogoutPage() {
      **const auth = useAuth()**
    
      const logout = (e) => {
        e.preventDefault();
        **auth.logout()**
      }
    
      return (
        <>
          <h1>Logout</h1>
    
          <form onSubmit={logout}>
            <label>驴Seguro de que quieres salir?</label>
    
            <button type="submit">Salir</button>
          </form>
        </>
      );
    }
    
    export { LogoutPage };
    
  • Modificamos ProfilePage para mostrar el nombre del usuario logeado.

    import React from "react";
    import { useAuth } from "../api/auth";
    
    function ProfilePage() {
      **const auth = useAuth()**
    
      return (
        **<>
          <h1>Perfil</h1>
          <p>Welcome, {auth.user.username}</p>
        </>**
      );
    }
    
    export { ProfilePage };
    

<aside>
馃挕 En la siguiente clase manejaremos las rutas que seran privadas, es decir las que necesitar谩n autentificaci贸n para ingresar; y las rutas p煤blicas, que ser谩n las de autentificaci贸n.

</aside>

Mi aporte, hasta le puse en el perfil la contrase帽a jaja

Despu茅s de 3 veces que vi la clase pude entender bien todo el proceso de Login y Logout, gracias teacher!!!

Discriminar no siempre es malo, sacar a Freddy de estos permisos es una buena manera de trabajo, ya que, cada quien tiene una chamba y autonom铆a.

En otras palabras, estos cursos discriminan informaci贸n. As铆 es, informaci贸n que no es relevante o que es falsa o de baja calidad.

Ya que actualmente rect-router est谩 en la versi贸n 6.8 he estado usando las nuevas caracter铆sticas.
As铆 fue como acomod茅 las rutas:

const router = createHashRouter([
  { 
    element: <AuthProvider/>,
    children:[
      {  
        path: "/",
        element:<Layout/>,
        errorElement: <ErrorPage/>,
        children:[  
          {
            index:true,
            path: "/",
            element:<HomePage className="container"/>,
          },
          {
            path: "/login",
            element:<LonginPage/>,
          },
          {
            path: "/logout",
            element:<LogoutPage/>,
          },
          {
            path: "/profile",
            element:<ProfilePage/>,
          },
          {
            path: "/blog",
            element:<BlogPage/>,
            loader:postLoader,

          },
          {
            path: "/blog-post/:slug",
            element:<BlogPost/>,
            loader:loaderBlogPost,  
          },
        ]
      } 
    ]
  },
])

function App() {
  
  return (
    <React.Fragment>
      <RouterProvider router={router}/>
    </React.Fragment>

)
}

<AuthProvider/> Tiene como hijos al resto de las rutas para poder compartir el contexto. Tambi茅n tengo un componente Layout el cual uso como base agregar tanto el men煤 como las rutas hijas que se rendericen dentro de 茅l dependiente de la url.

As铆 se ve el componente <AuthProvider/>:

import React from "react";
import { Outlet, useNavigate } from "react-router-dom";



const AuthContext = React.createContext();

function AuthProvider(){
    const [username, setUsername] = React.useState(null);
    const navigate = useNavigate();

    const login = ()=>{
        navigate("/profile");
    }
    const logout = ()=>{
        navigate("/");
    }
    
    const auth = {username, login, logout};
    return(
        <AuthContext.Provider value={auth}>
            <Outlet></Outlet>
        </AuthContext.Provider>
    )
}

function useAuth(){
    const data = React.useContext(AuthContext);
    return data
}

export {AuthProvider, useAuth}

Haciendo uso de un componete especial de react-router llamado Outlet; se puede traer a los hijos(childrens) especificados en las rutas.

Hasta el momento funcion贸 todo el ejercicio de esta clase.