Introducci贸n al curso avanzado de React

1

Qu茅 necesitas para este curso y qu茅 aprender谩s sobre React.js

2

Proyecto y tecnolog铆as que usaremos

Preparando el entorno de desarrollo

3

Clonando el repositorio e instalando Webpack

4

Instalaci贸n de React y Babel

5

Zeit es ahora Vercel

6

Linter, extensiones y deploy con Now

Creando la interfaz con styled-components

7

驴Qu茅 es CSS-in-JS?

8

Creando nuestro primer componente: Category

9

Creando ListOfCategories y estilos globales

10

Usar informaci贸n real de las categor铆as

11

Creando PhotoCard y usando react-icon

12

SVGR: de SVG a componente de ReactJS

13

Creando animaciones con keyframes

Hooks

14

驴Qu茅 son los Hooks?

15

useEffect: limpiando eventos

16

useCategoriesData

17

Usando Intersection Observer

18

Uso de polyfill de Intersection Observer e imports din谩micos

19

Usando el localStorage para guardar los likes

20

Custom Hooks: useNearScreen y useLocalStorage

GraphQL y React Apollo

21

驴Qu茅 es GraphQL y React Apollo? Inicializando React Apollo Client y primer HoC

22

Par谩metros para un query con GraphQL

23

Usar render Props para recuperar una foto

24

Refactorizando y usando variables de loading y error

25

Usando las mutaciones con los likes

Reach Router

26

驴Qu茅 es Reach Router? Creando la ruta Home

27

Usando Link para evitar recargar la p谩gina

28

Creando la p谩gina Detail

29

Agregando un NavBar a nuestra app

30

Estilando las p谩ginas activas

31

Rutas protegidas

Gesti贸n del usuario

32

Introducci贸n a React.Context

33

Creaci贸n del componente UserForm; y Hook useInputValue

34

Estilando el formulario

35

Mutaciones para registro

36

Controlar estado de carga y error al registrar un usuario

37

Mutaciones para iniciar sesi贸n

38

Persistiendo datos en Session Storage

39

Hacer like como usuario registrado

40

Mostrar favoritos y solucionar fetch policy

41

Cerrar sesi贸n

Mejores pr谩cticas, SEO y recomendaciones

42

脷ltimos retoques a las rutas de nuestra aplicaci贸n

43

React Helmet

44

Midiendo el performance de nuestra app y usando React.memo()

45

React.lazy() y componente Suspense

46

Usando PropTypes para validar las props

47

PWA: generando el manifest

48

PWA: soporte offline

49

Testing con Cypress

Conclusiones

50

隆Felicidades!

No tienes acceso a esta clase

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

Aprende todo un fin de semana sin pagar una suscripci贸n 馃敟

Aprende todo un fin de semana sin pagar una suscripci贸n 馃敟

Reg铆strate

Comienza en:

3D
21H
46M
9S
Curso de React Avanzado

Curso de React Avanzado

Miguel 脕ngel Dur谩n

Miguel 脕ngel Dur谩n

Rutas protegidas

31/50
Recursos

Con el m茅todo render props realizaremos rutas de autenticaci贸n para saber si el usuario ha iniciado sesi贸n o no y podremos mostrar contenido dependiendo de las props que le estemos pasando.

Aportes 28

Preguntas 1

Ordenar por:

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

o inicia sesi贸n.

Bueno a mi personalmente, me gusta tener las rutas separadas en un componente鈥 Me parece que como desarrollador algo que siempre vas a ver son las rutas para entender el sistema al igual que ves el package.json
A si que les dejo como separe las rutas鈥

App.js

import React from 'react'
import { GlobalStyle } from './styles/GlobalStyles'
import { Logo } from './components/Logo/Index'
import { NavBar } from './components/NavBar/index'
import { Route } from './router/Router'

export const App = () => (
  <>
    <Logo />
    <GlobalStyle />
    <Route />
    <NavBar />
  </>
)

Router.js

import React from 'react'
import { Router } from '@reach/router'
import { Home } from '../pages/Home'
import { Detail } from '../pages/Detail'
import { PrivateRoute } from './PrivateRoute'

const isAuth = false

export const Route = () => (
  <>
    <Router>
      <Home path='/' />
      <Home path='/pet/:id' />
      <Detail path='/detail/:id' />
    </Router>
    <PrivateRoute isAuth={isAuth} />
  </>
)

PrivateRoute.js

import React from 'react'
import { Router } from '@reach/router'
import { Favs } from '../pages/Favs'
import { NotRegisteredUser } from '../pages/NotRegisteredUser'
import { User } from '../pages/User'

export const PrivateRoute = ({isAuth}) => {
  return (
    <Router>
      {
        isAuth ? (
          <>
            <Favs path='/favs' />
            <User path='/user' />
          </>
        ) : (
          <>
            <NotRegisteredUser path='/favs' />
            <NotRegisteredUser path='/user' />
          </>
        )
      }
    </Router>
  )
}

Inclusive creo que se puede sacar el router De privateRouter para a si solo declararlo en un lugar solo

Un poquito m谩s c贸modo de utilizar en la actualidad mediante react-router-dom, utilizando el prop render de Route:

import { Route, Switch, BrowserRouter as Router, Redirect } from 'react-router-dom'
import { Logo } from '../components/Logo'
import { ListOfCategories } from '../components/ListOfCategories'
import { Details } from '../pages/Details'
import { Home } from '../pages/Home'
import { Navbar } from '../components/Navbar'
import { Favorite } from '../pages/Favorites'
import { Register } from '../pages/Register'
import { User } from '../pages/User'

const isLogged = true

export const Routes = () => {
  return (
    <Router>
      <Logo />
      <ListOfCategories />
      <Switch>
        <Route exact path='/' component={Home} />
        <Route exact path='/category/:id' component={Home} />
        <Route exact path='/details/:id' component={Details} />
        <Route exact path='/favs' render={() => isLogged ? <Favorite /> : <Redirect to='/register' />} />
        <Route exact path='/user' render={() => isLogged ? <User /> : <Redirect to='/register' />} />
        <Route exact path='/register' component={Register} />
      </Switch>
      <Navbar />
    </Router>
  )
}

.
V铆deo actualizado del profesor @midudev al 2021: https://www.youtube.com/watch?v=9CYuUNPbP34
.
PD: Este curso est谩 muy bueno, pero en serio, ya huele a encerrao. 隆Actualizaci贸n YA!

Buenas, para los que est茅n usando React Router v6, implement茅 un condicional dentro del element de cada Route:

import React, { useState } from "react";
import { BrowserRouter, Route, Routes } from "react-router-dom";
import { GlobalStyle } from "./styles/GlobalStyles";

import { Logo } from "./components/Logo";
import { Home } from "./pages/Home";
import { Detail } from "./pages/Detail";
import { NavBar } from "./components/NavBar";
import { User } from "./pages/User";
import { Favs } from "./pages/Favs";
import { NotRegisteredUser } from "./pages/NotRegisteredUser";

export const App = () => {
  const [isLogged, setIsLogged] = useState(true);

  return (
    <BrowserRouter>
      <GlobalStyle />
      <Logo />
      <Routes>
        <Route path='/' element={<Home />} />
        <Route path='/pet/:id' element={<Home />} />
        <Route path='/detail/:detailId' element={<Detail />} />
        <Route path='/favs' element={isLogged ? <Favs /> : <NotRegisteredUser />} />
        <Route path='/user' element={isLogged ? <User /> : <NotRegisteredUser />} />
      </Routes>
      <NavBar />
    </BrowserRouter>
  );
}

Espero les sirva, saludos!

una consulta, esta variable en el mundo real puede ser modificada con herramientas del desarrollador que proveen los navegadores?? lo pregunto por si esta soluci贸n podr铆a ser puesta en producci贸n as铆 como esta.

Hola compa帽eros, as铆 lo plantee usando react-router-dom

import React from 'react'
import { Logo } from './components/Logo'
import { Home } from './pages/Home'
import { BrowserRouter, Routes, Route } from 'react-router-dom'
import { GlobalStyle } from './components/styles/GlobalStyles'
import { NavBar } from './components/NavBar'

import { Detail } from './pages/Detail'
import { Favorites } from './pages/Favs'
import { User } from './pages/User'
import { NotRegisteredUser } from './pages/NotRegistered'

const App = () => {
  const isLogged = false

  return (
    <BrowserRouter>
      <GlobalStyle />
      <Logo />
      <Routes>
        <Route exact path='/' element={<Home />} />
        <Route path='/pet/:id' element={<Home />} />
        <Route path='/detail/:id' element={<Detail />} />
        <Route path='/favs' element={isLogged ? <Favorites /> : <NotRegisteredUser />} />
        <Route path='/user' element={isLogged ? <User /> : <NotRegisteredUser />} />
      </Routes>
      <NavBar />
    </BrowserRouter>
  )
}

export { App }

Ya hay m茅todos m谩s sencillos para renderizar rutas privadas con react router dom

export const App: FC = () => {
  const isLogged = false;
  return (
    <Router>
      <div>
        <GlobalStyled />
        <Logo />
        <Switch>
          <Route exact path="/" component={Home} />
          <Route path="/pet/:id" component={Home} />
          <Route path="/detail/:detailId" component={Detail} />
          <Route path="/favs" render={ ()=> isLogged && <Favs /> || <NotRegisteredUser /> }/>
          <Route path="/user" render={ ()=> isLogged && <User /> || <NotRegisteredUser /> }/>
        </Switch>
        <NavBar />
      </div>
    </Router>
  );
};

Hola, les dejo mi implementaci贸n con Next.js:

Cre茅 un contexto para manejar la autenticaci贸n, en la carpeta context/auth.js:

import { createContext, useContext } from 'react';

export const AuthContext = createContext();

export function useAuth() {
  return useContext(AuthContext);
}

En _app.js cre茅 un estado para manejar la autenticaci贸n y puse el contexto cubriendo toda la app:

function MyApp({ Component, pageProps }) {
  const [authTokens,setAuthTokens] = useState(true)
  return (
    <AuthContext.Provider value={{ authTokens, setAuthTokens }}>
      <ApolloProvider client={client}>
        <GlobalStyle />
        <Logo />
        <Component {...pageProps} />
        <NavBar />
      </ApolloProvider>
    </AuthContext.Provider>
  );
}

Tambi茅n cre茅 un nuevo componente que se llama PrivateRoute, en el cual hago uso del contexto para saber si la autenticaci贸n ya se dio:

import React from 'react';
import {useAuth} from 'context/auth'
const PrivateRoute = ({children}) => {
    const {authTokens} = useAuth()
    return <>{!authTokens ? <p>Not Logged</p> : <>{children}</>}</>;
}
 
export default PrivateRoute;

Finalmente, dentro de cada componente que tengo que proteger, uso el PrivateRoute, por ejemplo en favs:

import React from 'react';
import PrivateRoute from '@components/PrivateRoute'
const Favoritos = () => {
    
    return (
        <PrivateRoute>
            <p>Favs</p>
        </PrivateRoute>
    );
}
 
export default Favoritos;

En este punto, faltar铆a en _app.js hacer toda la l贸gica de autenticaci贸n.

Les dejo mi repositorio en Nextjs con la soluci贸n:

Mi maldici贸n de los () contin煤a, ahora me gast茅 m谩s de 15 min con un ) mal puesto en el Router鈥

Comienzo a creer que no tengo talento para esto鈥

Uds. ven la ventaja de los render props ? No los veo muy pr谩ctico, puedo hacer las 鈥渞utas protegidas鈥 con esto sin tanta complejidad:

        {isAuth ? (
          <>
            <Favs path="/favs" />
            <User path="/user" />
          </>
        ) : (
          <>
            <NotRegisteredUser path="/favs" />
            <NotRegisteredUser path="/user" />
          </>
        )}
        	

Les comparto una gu铆a resumida de React Context en freecodecamp que repasa la forma de uso y definici贸n, los casos de uso mas comunes y para lo que no se recomienda su uso por los problemas que puede crear.
Tambi茅n lo contrasta con Redux.
Est谩 en ingl茅s y su redacci贸n no es la mejor pero se entiende bien.

https://www.freecodecamp.org/news/react-context-for-beginners/

Espero les sume!!!

Es m谩s f谩cil hoy en d铆a con React Router V6

import { BrowserRouter, Route, Routes, Navigate } from 'react-router-dom';
import { GlobalStyle } from './styles/GlobalStyles';
import { Logo } from './components/Logo/index';
import { Home } from './pages/Home';
import { Detail } from './pages/Detail';
import { Navbar } from './components/Navbar/index';
import { Favs } from './pages/Favs';
import { User } from './pages/User';
import { NotRegisteredUser } from './pages/NotRegisteredUser';

const userLogged = false;

function App() {
	return (
		<>
			<BrowserRouter>
				<GlobalStyle />
				<Logo />
				<Routes>
					<Route
						path='/'
						element={userLogged ? <Home /> : <Navigate to='/login' />}
					/>
					<Route
						path='/favs'
						element={userLogged ? <Favs /> : <Navigate to='/login' />}
					/>
					<Route path='/user' element={<User />} />
					<Route path='/login' element={<NotRegisteredUser />} />
					<Route path='/pet/:id' element={<Home />} />
					<Route path='/detail/:detailId' element={<Detail />} />
				</Routes>
				<Navbar />
			</BrowserRouter>
		</>
	);
}

export default App;

<Route
            exact
            path="/favs"
            component={isAuth ? Favs : NotRegisteredUser}
          />
          <Route
            exact
            path="/user"
            component={isAuth ? User : NotRegisteredUser}
          />

En ves de usar dos veces el componente de NoRegisterUser use lo siguiente

 <Router>
      <Register default  path='/register'/>
 </Router>

una pregunta. Si hago mutations a la base de datos se cargan? Osea mis cambios los pueden usar otros que tengan acceso a la api?

tengo una duda con los archivos veo que la extensi贸n es js y no jsx, existe alguna diferencia actualmente entre usar js o jsx?? puedo usar react con archivos .ts ??

Para quien est茅 usando React Router 6.4 y est茅 usando la nueva funci贸n createBrowserRouter(), as铆 lo hice yo en App.js:

import React from 'react'
import { GlobalStyle } from './styles/GlobalStyle'
import { Logo } from './components/Logo'
import { Home } from './pages/Home'
import { createBrowserRouter, Outlet, RouterProvider } from 'react-router-dom'
import { Detail } from './pages/Detail'
import { Favs } from './pages/Favs'
import { NotRegisteredUser } from './pages/NotRegisteredUser'
import { User } from './pages/User'
import { NavBar } from './components/NavBar'

const isUserLogged = true

const Container = () => (
  <>
    <Logo />
    <Outlet />
    <NavBar />
  </>)

const router = createBrowserRouter(([
  {
    path: '/',
    element: <Container />,
    children: [
      {
        path: '/',
        element: <Home />
      },
      {
        path: '/pet/:id',
        element: <Home />
      },
      {
        path: '/detail/:detailId',
        element: <Detail />
      },
      {
        path: '/favs',
        element: isUserLogged ? <Favs /> : <NotRegisteredUser />
      },
      {
        path: '/user',
        element: isUserLogged ? <User /> : <NotRegisteredUser />
      }
    ]
  }
]))

export const App = () => {
  return (
    <div>
      <GlobalStyle />
      <RouterProvider router={router} />
    </div>
  )
}

App.js

import React from "react";
import { BrowserRouter, Routes, Route} from "react-router-dom";
//styles
import { GlobalStyle } from "./Styles/GlobalStyles";
// import { Routes } from './Routes'
import { Home } from './Pages/Home';
import { Detail } from "./Pages/Detail";
import { Favs } from "./Pages/Favs";
import { User } from "./Pages/User";
import { NotRegisteredUser } from "./Pages/NotRegisteredUser";

import { Logo } from './Components/Logo';
import { NavBar } from './Components/NavBar';

const UserLogged = ({children}) =>{
    return children({isAuth: false})
}

export const App = () =>{
    const  urlParams = new window.URLSearchParams(window.location.search)
    const detailId = urlParams.get('detail')
    console.log(detailId)
    return (
        <BrowserRouter>
        <GlobalStyle />
        <Logo />
        <Routes>
            <Route path='/' element={<Home />} />
            <Route path='/pet/:id' element={<Home />} />
            <Route path='/detail/:id' element={<Detail />} />
        </Routes>
        <UserLogged>
            {
                ({isAuth}) =>
                    isAuth
                    ?
                    <Routes>
                        <Route path='/favs' element={<Favs />} />
                        <Route path='/user' element={<User/>} />
                    </Routes>
                    :
                    <Routes>
                        <Route path='/favs' element={<NotRegisteredUser />} />
                        <Route path='/user' element={<NotRegisteredUser />} />
                    </Routes>
            }
        </UserLogged>
        <NavBar />
        </BrowserRouter>
    )
} 

Con react-router-dom

const UserLogged = ({ children }) => {
    return children({ isAuth: false });
}

const App = () => {
    return (
    <BrowserRouter>
            <GlobalStyle />
            <Logo />
            <Switch>
                <Route exact path='/'render={(props) =><Home {...props} />} />
                <Route exact path='/pet/:id'render={(props) =><Home {...props} />} />
                <Route exact path='/detail/:detailId' component={Detail}/>
                <UserLogged>
                    {
                        ({ isAuth }) =>
                            isAuth
                            ? <>
                                <Route exact path='/favs' component={Favs} />
                                <Route exact path='/user' component={User} />
                              </>
                            : <>
			         // ESTA ES OTRA FORMA DE UTILIZAR 1 RUTA EN LUGAR DE 2
                                  <Route component={NotRegisteredUser} />
                              </>
                    }
                </UserLogged>
     </Switch>
     <NavBar />
    </BrowserRouter>
    );
};

es decir esto ser铆a como un guard驴?

se puede hacer como en Angular que en la ruta le dices si usa un Auth y asi no creas un Route para cada secci贸n驴? lo veo muy repetido eso NotRegistedUser con el path para favs y user驴?

{ 
    path: 'profile',
    component: ProfileComponent,
    canActivate: [AuthGuard] 
  },```

Me gusta m谩s esta validaci贸n y reach/router lo hace tan simple

Hola, 驴como hago que al guardar el eslint me solucione las identaciones?

//Lo que hago es redireccionar si no esta autorizado
const Routes = () => (
<BrowserRouter>
<Switch>
<Route
path="/locales"
strict
sensitive
render={() => {
if(userid){
return <Locales />
}else{
return <Redirect from="/locales" to="/" />
}
}}
/>

Me encantan las Render Props!

import React from 'react';

import { Router } from '@reach/router';

import Layout from './components/Layout/Layout';
import Home from './pages/Home';
import Details from './pages/Details';
import Favorites from './pages/Favorites';
import User from './pages/User';
import UnregisteredUser from './pages/UnregisteredUser';

import useUserLogged from './hooks/useUserLogged';


const App = () => {
  const { isAuth } = useUserLogged(true);

  return (
    <>
      <Layout>
        <Router>
          <Home path="/" />
          <Home path="/pet/:CategoryId" />
          <Details path="/detail/:detailId" />
        </Router>
        {isAuth
          ? (
            <Router>

              <Favorites path="/favorites" />
              <User path="/user" />
            </Router>
          )
          : (
            <Router>

              <UnregisteredUser path="/favorites" />
              <UnregisteredUser path="/user" />
            </Router>
          )}

      </Layout>
    </>
  );
};

export default App;

Con el m茅todo render props realizaremos rutas de autenticaci贸n para saber si el usuario ha iniciado sesi贸n o no y podremos mostrar contenido dependiendo de las props que le estemos pasando.

Tenia el problema que en el navbar el home siempre me aparec铆a activo, lo solucion茅 cambiando el / por el /home, creo que si por ejemplo estas en /user cuenta como activo la ruta / y la ruta /user

Estoy implementando rutas en un proyecto de la siguiente forma :

<Layout>
       <Router>
         <Home path="/" />
         {!isAuth && <Login path="/login"  /> }
         {!isAuth && <Redirect from='/user/questionnaires/new' to='/login' noThrow />}
         {!isAuth && <Redirect from='/user/questionnaires/detail/:detailId' to="/login" noThrow />}
         {!isAuth && <Redirect from='/user' to='/login' noThrow />}
         {isAuth &&  <Redirect from='/login' to='/user' noThrow />}      
         <UserHome path="/user"   />
         <NewQuestionary path="/user/questionnaires/new" />
         <QuestionnaireDetail path="/user/questionnaires/detail/:detailId" />
       </Router>
     </Layout>

Pero este redirect

  {!isAuth && <Redirect from='/user/questionnaires/detail/:detailId' to="/login" noThrow />}

me manda este error :

Uncaught Invariant Violation: <Redirect from="/user/questionnaires/detail/:detailId to="/login"/> has mismatched dynamic segments, ensure both paths have the exact same dynamic segments.

驴como debo configurar mi redirect para que funcione de forma correcta?

C贸digo: