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

Curso de React Avanzado

Curso de React Avanzado

Miguel Ángel Durán

Miguel Ángel Durán

Mostrar favoritos y solucionar fetch policy

40/50
Recursos

Aportes 28

Preguntas 7

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

o inicia sesión.

con hooks

/* eslint-disable import/no-extraneous-dependencies */
import { useQuery } from '@apollo/react-hooks';
import qgl from 'graphql-tag';


const GET_FAVORITES = qgl`
query getFavs {
    favs {
      id
      categoryId
      src
      likes
      userId
    }
  }
`;


const useGetFavorites = () => {
  const { data, error, loading } = useQuery(GET_FAVORITES, { fetchPolicy: 'cache-and-network' });
  return { data, loading, error };
};


export default useGetFavorites;

fetchPolicy=‘cache-and-network’ va a la red y obtiene una version fresca q almacena en el cache. Este es mejor por si hay acceso offline a la app.

import styled from 'styled-components'
import { Link as LinkRouter } from '@reach/router'

export const Link = styled(LinkRouter)`
    border-radius: 8px;
    box-shadow: 0 0 8px rgba(0,0,0,.3);
    display: inline-block;
    margin: 1%;
    overflow: hidden;
    position: relative;
    width: 31.33%;
    &:after {
        content: '';
        display: block;
        padding-bottom: 100%;
    }
`

export const Grid = styled.div`
    padding-top: 32px;
`

export const Image = styled.img`
    object-fit: cover;
    height: 100%;
    width: 100%;
    position: absolute;

Tengo un problema muy seguido me sale este error cuando entro a mi Favs page

Error GraphQL error: user does not exist

Sabran que sera?
Es como si se me borrara la base de datos de graphql 😒

26/04/2021 El codigo del video ya no funciona… Dejo el código (que se que se puede mejorar pero hasta hoy funciona…) una vez acabado el video (Y) espero le sirva a alguien
GetFavorites:

import { useQuery, gql } from '@apollo/client'
import React from 'react'
import {ListOfFavs} from '../components/ListOfFavs'

const GET_FAVORITES = gql`
query getFavs {
    favs {
      id
      categoryId
      src
      likes
      userId
    }
  }
`;

const FavsWithQuery = () => {
    const { loading, data, error } = useQuery(GET_FAVORITES, {
        fetchPolicy: 'cache-and-network'
      })
      return { loading, data, error }
};

export const RenderProp = () => {
    const {loading, data, error} = FavsWithQuery();
    if(loading) return <p>Loading...</p>
    if(error) return <p>Error...</p>
    const {favs} = data

    return <ListOfFavs favs={favs} />

}

ListOfFavs y styles si funciona tal cual el video

Dejo mi aporte del uso de hooks para realizar el query GET_FAVS.

import { useQuery } from "@apollo/react-hooks";
import { gql } from "apollo-boost";

const GET_FAVS = gql`
  query getFavs {
    favs {
      id
      categoryId
      src
      likes
      userId
    }
  }
`;

export const useGetFavs = () => {
  const { data, loading, error } = useQuery(GET_FAVS, {
    fetchPolicy: "cache-and-network"
  });

  return { data, loading, error };
};

Hola chicos, intenté usar la nueva forma con hooks que han dejado en los comentarios, sin embargo, mi useQuery seguía sin traer los datos actualizados, así que usé useEffect y extraí la propiedad refetch de useQuery

  const { loading, error, data, refetch } = useQuery(GET_FAVS_PHOTO)
  useEffect(() => refetch(), [])

Básicamente estoy diciendo que vuelva a hacer un fetch cada vez que el componente se renderice. Si quieren saber cómo funciona el refetch les dejo la documentación https://www.apollographql.com/docs/react/data/queries/#refetching

04/06/2022 (hooks, react-router-dom, @apollo/client)
src/hooks/useGetFavorite.js:

import { useQuery, gql } from '@apollo/client'

const GET_FAVORITES = gql`
    query getFavs {
        favs {
            id 
            categoryId
            src
            likes
            userId
        }
    }
`

export const useGetFavorite = ()=> {
    const {data, loading, error} = useQuery(GET_FAVORITES, {
        fetchPolicy: 'cache-and-network'
    })

    return {data , loading, error}
}

src/components/ListOfFavs/index.js:

import React from 'react';
import { Link, Grid, Image } from './styles';

export const ListOfFavs = ({ favs = [] })=> {
    return (
        <Grid>
            {
                favs.map(fav => (
                    <Link key={fav.id} to={`/detail/${fav.id}`} >
                        <Image src={fav.src} />
                    </Link>
                ))
            }
        </Grid>
    )
}

src/components/ListOfFavs/styles.js:

import styled from 'styled-components'
import { Link as LinkRouter } from 'react-router-dom'

export const Link = styled(LinkRouter)`
    position: relative;
    border-radius: 8px;
    box-shadow: 0 0 8px rgba(0,0,0,.3);
    display: inline-block;
    margin: 1%;
    overflow: hidden;
    width: 31.33%;
    &:after {
       content: "";
        display: block;
        padding-bottom: 100%;
    }
`

export const Grid = styled.div`
    padding-top: 32px;
`

export const Image = styled.img`
    object-fit: cover;
    height: 100%;
    width: 100%;
    position: absolute;
`

src/pages/Favs.js:

import React from 'react';
import { useGetFavorite } from '../hooks/useGetFavorite';
import { ListOfFavs } from '../components/ListOfFavs';

export const Favs = ()=> {
    const { data, loading, error } = useGetFavorite()

    if (loading) return 'loading...'
    if (error) return 'error'

    return <ListOfFavs favs={data.favs} />
}

Pensando en la reutilizacion de componentes, porque en lugar de crear un nuevo componente ListOfFavs que en esencia es lo mismo que el ListOfPhotoCards, no se modifica el componente (ListOfPhotoCards) para que reciba las fotos por props y se hace un hook en cada page (Home, Favs) para que obtenga las photos que se necesitan?

Creo que se esta haciendo doble trabajo.

Un aporte de como configurar el policy en los hooks

import { useQuery, gql } from '@apollo/client'
const GET_FAVS = gql`
query getFavs {
  favs {
    id
    categoryId
    src
    likes
    userId
  }
}
`
export const useGetFavorites = id => {
  const { loading, data, error } = useQuery(GET_FAVS, {
    fetchPolicy: 'network-only'
  })
  return { loading, data, error }
}

Como es que se le pasa el header de autenticación ??

como valida eso? automaticamente Apolo lo detecta?’

import { Query } from '@apollo/client/react/components'

El componente QUERY a fecha de hoy julio 2021 se encuentra en esa ruta…

Así me funcionó el GetFavorities.js al día de hoy:

import { useQuery, gql } from '@apollo/client'
import React from 'react'
import { ListOfFavs } from '../components/ListOfFavs'

const GET_FAVORITES = gql`
  query getFavs {
    favs {
      id
      categoryId
      src
      likes
      userId
    }
  }
`

const RenderProp = ({ loading, data, error }) => {
  if (loading) return <p>Loading...</p>
  if (error) return <p>Error...</p>
  const { favs } = data

  return <ListOfFavs favs={favs} />
}

export const FavsWithQuery = () => {
  const { loading, error, data } = useQuery(GET_FAVORITES, {
    fetchPolicy: 'cache-and-network'
  })

  return <RenderProp loading={loading} data={data} error={error} />
}

Yo reusé el componente ListOfPhotoCard (yo lo llamo ListFeedCard) de la siguiente manera:
Nota: useGetFavorites() Es mi hook para obtener los datos, uso los hooks de GraphQl

export const FavsPage = () => {
  const { data, loading, error } = useGetFavorites()
  const [favs, setFavs] = useState([])

  useEffect(() => {
    if (data) setFavs(data.favs)
  }, [data])

  return <ListFeedCard list={favs} error={error} loading={loading} />
}

Me esta encantando este curso, super super completo, con detalles en los errores y posibles errores! Muy contento de haberlo iniciado!

Hola Chicos, vengo del futuro y Les dejo una mejora en PhotoCardWithQuery.js para evitar pasar data empty al renderizar PhotoCard:

const renderProp = ({ loading, error, data = { photo: {} } }) => {
//   if (loading) return <p>Loading... </p>
  if (error) return <p>Error!</p>
  if (data) {
    const { photo = {} } = data
    if (Object.keys(photo).length) {
      return <PhotoCard {...photo} loading={loading} />
    }
  }
  return null
}```

Esto les ayudara mas adelante cuando vean validaciones dentro de los proptypes.
Saludos 🐱‍🏍

Yo realiza el codigo utilizando hooks:

import { gql, useQuery } from '@apollo/client';

const GET_FAVORITES = gql`
query getFavs{
  favs{
    id
    categoryId
    src
    likes
    userId
  }
}
`;

export const useGetFavPhotos = ()=>{
  const { loading, data, error } = useQuery(GET_FAVORITES,{
    fetchPolicy: 'cache-and-network'
  });
  return { loading, data, error }
}

import React from "react"
import { ListOfFavs } from "../components/ListOfFavs"
import { useGetFavPhotos } from "../hooks/useGetFavPhotos";

export const Favs = ()=>{
  const { loading, data, error } = useGetFavPhotos();
  if(loading) return <p>Loading...</p>
  if(error)   return <p>Error...</p>
  const {favs} = data;
  return (
    <>
      <ListOfFavs favs={favs} />
    </>
  )
}

import React from 'react'
import { Grid, Image, Link } from './styles'

export const ListOfFavs = ({favs = []})=>{
  return (
    <Grid>
      {
        favs.map(fav=>(
          <Link  key={fav.id} to={`/detail/${fav.id}`} >
            <Image src={fav.src} />
          </Link>
        ))
      }
    </Grid>
  )
}

import styled from 'styled-components'
import { Link as LinkRouter } from 'react-router-dom'

export const Link = styled(LinkRouter)`
  border-radius: 8px;
  box-shadow: 0 0 8px rgba(0,0,0,.3);
  display: inline-block;
  margin: 1%;
  overflow: hidden;
  position: relative;
  width: 31.33%;
  &:after{
    content:'';
    display: block;
    padding-bottom: 100%;
  }
`

export const Grid = styled.div`
  padding-top: 32px;
`

export const Image = styled.img`
  object-fit: cover;
  height: 100%;
  width: 100%;
  position: absolute;
`

Hola a todos, estoy en 05/04/2022
Ya no hay ese problema de cache, entiendo que por esta parte del codigo:

const client = new ApolloClient({
  ...
  cache: new InMemoryCache(),
  ...
})

En cuanto al codigo utiliado, emplee hooks:
hooks/useGetFavs

import React from 'react'
import { ListOfFavs } from '../components/ListOfFavs';
import { useQuery, gql } from '@apollo/client';

const GET_FAVORITES = gql`
  query getFavs {
    favs {
      id
      categoryId
      src
      likes
      userId
    }
  }
`;

const FavsWithQuery = () => {
  const { loading, data, error } = useQuery(GET_FAVORITES, {
      fetchPolicy: 'cache-and-network'
  })
  return { loading, data, error }
};

export const RenderProp = () => {
  const {loading, data, error} = FavsWithQuery();
  if(loading) return <p>Loading...</p>
  if(error)   return <p>Error...</p>
  const {favs} = data
  return <ListOfFavs favs={favs} />
}

pages/Favs

import React from 'react'
import { RenderProp } from '../hooks/useGetFavs'

export const Favs = ()=>(
  <>
    <h1>Favs</h1>
    <RenderProp />
  </>
)

components/ListOfFavs:

import React from 'react'
import { Grid, Image, Link } from './styles'

export const ListOfFavs = ({favs = []})=>{
  return (
    <Grid>
      {
        favs.map(fav=>(
          <Link  key={fav.id} to={`/detail/${fav.id}`} >
            <Image src={fav.src} />
          </Link>
        ))
      }
    </Grid>
  )
}

components/ListOfFavs/styles

import styled from 'styled-components'
import { Link as LinkRouter } from 'react-router-dom'

export const Link = styled(LinkRouter)`
  border-radius: 8px;
  box-shadow: 0 0 8px rgba(0,0,0,.3);
  display: inline-block;
  margin: 1%;
  overflow: hidden;
  position: relative;
  width: 31.33%;
  &:after{
    content:'';
    display: block;
    padding-bottom: 100%;
  }
`

export const Grid = styled.div`
  padding-top: 32px;
`

export const Image = styled.img`
  object-fit: cover;
  height: 100%;
  width: 100%;
  position: absolute;
`

Exitos camaradas

Hola, les dejo el avance de mi proyecto hecho en Nextjs:

https://github.com/danyel117/petgram-platzi/tree/favorites

Hola Devs:
-Aqui les traigo un aporte, les comparto este articulo que habla bien sobre el fetchPolicy, espero que les ayude a entender mejor y sacarle el maximo provecho: Click Aqui

Excelente!!

¿Se podría guardar los favoritos sin que se tenga que registrar?

Excelente

Esta solucion me parecio la mejor con hooks https://www.apollographql.com/docs/react/data/queries/#refetching

genial!!