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:

0D
17H
11M
34S
Curso de React Avanzado

Curso de React Avanzado

Miguel 脕ngel Dur谩n

Miguel 脕ngel Dur谩n

Mutaciones para registro

35/50
Recursos

De momento nuestro formulario no est谩 guardando la informaci贸n de registro en ning煤n lado, para ello vamos a usar un Mutation de GraphQL para mandarle la informaci贸n a nuestro backend y que nos regrese un JSON Web Token.

Para configurar esta Mutation vamos a crear un container llamado RegisterMutation.js con el siguiente c贸digo:

import React from 鈥榬eact鈥
import { Mutation } from 鈥榬eact-apollo鈥
import { gql } from 鈥榓pollo-boost鈥

const REGISTER = gql`
	mutation signup ($input: UserCredentials!) {
		signup (input: $input)
	}
`

export const RegisterMutation = ({ children }) => {
	return (
		<Mutation mutation={REGISTER}>
			{children}
		Mutation>
	)
}

Aportes 26

Preguntas 5

Ordenar por:

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

o inicia sesi贸n.

Puede que esta parte sea un poco confusa, pero es m谩s f谩cil de lo que parece. B谩sicamente lo que hacemos es pedir datos a travez de 3 componentes y recibirlos para mandarlos con GraphQL al servidor. Entonces dividamos este problema en tres:

  1. RegisterMutation: Este b谩sicamente se encarga de mandar los datos que pedimos envolviendo un children para poderle pasar la funci贸n que necesita ejecutar (register).

  2. NotRegisterUser: Este componente es el children que es envuelto y su funci贸n es conseguir los datos que necesita mandar (email y password), para ello va a pasar la funci贸n onSubmit por props para que otro componente trabaje con esta funci贸n. NotRegisterUser b谩sicamente va a armar la estructura para enviarla a RegisterMutation, pero no se encarga de conseguir los datos, solo los recibe. Nota: Tambi茅n recibe a activeAuth, esto para avisarle a la app que ya se hizo un login o registro.

  3. UserForm: este componente recibe por props la funci贸n onSubmit y solo tiene que ejecutarla (mandando los datos correspondientes), estos datos los toma de los <inputs>, entonces simplemente ejecuta la funci贸n onSubmit pasando estos datos.

Digamos que es una especie de loop, se piden los datos y despu茅s se regresan. Espero no haber confundido m谩s sobre el tema 馃槄 .

                               UTILIZANDO HOOKS

@pages/NotRegisteredUser.js

import React from 'react'
import Context from '../Context'
import { UserForm } from '../components/UserForm'
import { useRegisterMutation } from '../containers/RegisterMutation'


export const NotRegisteredUser = () => {
    const { registerMutation } = useRegisterMutation()
    
    return (
        <Context.Consumer>
            {
                ({activateAuth}) => {
                    const onSubmit = ({email, password}) => {
                        const input = { email, password }
                        const variables = { input }
                        registerMutation({ variables })
                        .then(activateAuth)
                    }
                    return <>
                        <UserForm onSubmit={onSubmit} title='Registrarse'/>
                        <UserForm onSubmit={activateAuth} title='Iniciar Sesion'/>
                    </>
                }
            }
        </Context.Consumer>
        // <h1>NotRegisteredUser</h1>
    )
}

@containers/RegisterMutation.js

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

const REGISTER = gql`
    mutation signup($input: UserCredentials!){
        signup(input: $input)
    }
`
export const useRegisterMutation = () => {
  const [registerMutation] = useMutation(REGISTER)

  return { registerMutation }
}

ACTUALIZACION 2021 y para quien utiliza react-router-dom, @apolo/client

1.- Mi Solucion es con hooks en RegisterMutation.js

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

const REGISTER = gql`
  mutation signup($input: UserCredentials!) {
    signup(input: $input)
  }
`;

export const useRegisterMutation = () => {
    const [registerMutation, { data, loading, error }] = useMutation(REGISTER);  
    return {registerMutation};
};

2.- En NotRegisteredUser.js:
Pd: Estoy utilizando el hook useContext(), en lugar de su Consumer

import React, { useContext } from 'react';
import UserForm from '../components/UserForm';

import AppContext from '../context/AppContext';
import { useRegisterMutation } from '../containers/RegisterMutation';

const NotRegisteredUser = () => {
    const { activateAuth } = useContext(AppContext);
    const { registerMutation } = useRegisterMutation();

    const onSubmit = ({email, password}) => {
        const input = { email, password }
        const variable = { input }
        registerMutation({variables: variable})
        .then(activateAuth);
    }

    return (
        <React.Fragment>
            <UserForm onSubmit={onSubmit} title='Registrarse'/>
            <UserForm onSubmit={activateAuth} title='Iniciar Sesion'/>
        </React.Fragment>
    );
}

export default NotRegisteredUser;

3.- UserForm.js

const UserForm = ({ onSubmit, title }) => {
    const [form, setForm] = useState({email: '',password: ''});

    const handleForm = e => {
        setForm({
            ...form,
            [e.target.name]: e.target.value,
        });
    }

    const handleSubmit = (event) => {
        event.preventDefault();
        onSubmit({ email: form.email, password: form.password });
    }

    return (
     <React.Fragment>
               <Title>{title}</Title>
                <Form onSubmit={handleSubmit}>
                <Input placeholder="Email" name="email" value={form.email} onChange={handleForm} />
                <Input placeholder="Password" name="password" type="password" value={form.password} onChange={handleForm} />

                <Button>{title}</Button>
            </Form>        
        </React.Fragment>
    );
}

export default UserForm;

Las clases est谩n en desorden, esta clase va despu茅s de la clase 鈥淓stilando el formulario鈥 y antes de la clase 鈥淐ontrolar estado de carga y error al registrar un usuario鈥

const REGISTER = gql`
  mutation signup($input:UserCredentials!) {
    signup (input: $input)
  }
`

Un aporte utilizando hooks!

import { gql, useMutation } from '@apollo/client'
const REGISTER_MUTATION = gql`
mutation signup($input: UserCredentials!) {
  signup (input: $input)
}
`

export const useRegisterMutation = () => {
  const [register, { loading, error }] = useMutation(REGISTER_MUTATION)
  return { register, loading, error }
}

Para utilizarlo

import React from 'react'
import Context from '../Context'
import { UserForm } from '../components/UserForm'
import { useRegisterMutation } from '../components/hooks/useRegisterMutation'

export const NotRegisteredUser = () => (
  <Context.Consumer>
    {
      ({ isAuth, activateAuth }) => {
        return (
          <>
            <Registro activateAuth={activateAuth} />
            <UserForm activateAuth={activateAuth} title='Iniciar sesi贸n' />
          </>
        )
      }
    }
  </Context.Consumer>
)

const Registro = ({ activateAuth }) => {
  const { register } = useRegisterMutation()
  const onSubmit = ({ email, password }) => {
    const input = { email, password }
    const variables = { input }
    register({ variables }).then(res => {
      activateAuth()
    })
  }
  return <UserForm onSubmit={onSubmit} title='Registrarse' />
}

Dejo mi c贸digo con react hooks:

FORM:

import React from 'react'

import { useInputValue } from '../../hooks/useInputValue'
import { Form, Input, Button, Title } from './styles'

// Register Hook
import useRegister from '../../hooks/useRegister'

const UserForm = ({ onSubmit, title }) => {
  const register = useRegister()
  const email = useInputValue('')
  const password = useInputValue('')

  const handleSubmit = async (e) => {
    e.preventDefault()
    try {
      await register({
        variables: {
          input: {
            email: email.value,
            password: password.value,
          },
        },
      })
      onSubmit()
    } catch (error) {
      console.log(error)
    }
  }
  return (
    <>
      <Title>{title}</Title>
      <Form onSubmit={handleSubmit}>
        <label>Email</label>
        <Input placeholder="Email" {...email} type="email" />
        <label>Password</label>
        <Input placeholder="Password" {...password} type="text" />
        <Button type="submit">{title}</Button>
      </Form>
    </>
  )
}

export default UserForm

MUTATION HOOK:

import { useMutation } from '@apollo/react-hooks'
import { gql } from 'apollo-boost'

const REGISTER = gql`
  mutation signup($input: UserCredentials!) {
    signup(input: $input)
  }
`

const useRegister = () => {
  const [register] = useMutation(REGISTER)

  return register
}

export default useRegister

Hola compa帽eros por si se llegan a atorar, este codigo es del 8 de noviembre de 2021. 馃槃

Container RegisterMutation.js

import React from 'react'
import { gql } from '@apollo/client'
import { Mutation } from '@apollo/client/react/components'

const REGISTER = gql`
  mutation signup($input: UserCredentials!){
    signup(input: $input)
  }
`

const RegisterMutation = ({ children }) => {
  return (
    <Mutation mutation={REGISTER}>
      {children}
    </Mutation>
  )
}

export { RegisterMutation }

Componente UserForm.jsx

import React from 'react'
import { useInputValue } from '../hooks/useInputValue'
import { Form, Input, Button, Title } from './styles/styledForm'

const UserForm = ({ onSubmit, title }) => {
  const email = useInputValue('')
  const password = useInputValue('')

  const handleSubmit = (e) => {
    e.preventDefault()
    onSubmit({ email: email.value, password: password.value })
  }

  return (
    <>
      <Title>{title}</Title>
      <Form onSubmit={handleSubmit}>
        <Input placeholder='email' {...email} />
        <Input type='password' placeholder='password' {...password} />
        <Button>{title}</Button>
      </Form>
    </>
  )
}

export { UserForm }

Componente NotRegistered.jsx

import React, { useContext } from 'react'
import { AppContext } from '../Context/Context'
import { UserForm } from '../components/UserForm'
import { RegisterMutation } from '../container/RegisterMutation'

const NotRegisteredUser = () => {
  const { activateAuth } = useContext(AppContext)

  return (
    <>
      <RegisterMutation>
        {
          (register) => {
            const onSubmit = ({ email, password }) => {
              const input = { email, password }
              const variables = { input }
              register({ variables }).then(activateAuth)
            }
            return <UserForm onSubmit={onSubmit} title='Registrarse' />
          }
        }
      </RegisterMutation>
      <UserForm onSubmit={activateAuth} title='Iniciar sesi贸n' />
    </>
  )
}

export { NotRegisteredUser }

Dejo igualmente mi repo https://github.com/onedrako/petstagram
Commit 8e39764 o 鈥淩egister new User with Form鈥

Un peque帽o aporte utilizando @apollo/react-hooks

NotRegisteredUser.js

import React from 'react'
import { useStateValue } from '../Context';
import { UserForm } from '../components/UserForm'
import { useMutation } from '@apollo/react-hooks'
import { SIGNUP_MUTATION } from '../graphql/mutations/AuthMutation'

export const NotRegisteredUserPage = () => {
  const [{ user }, dispatch] = useStateValue();
  const [ signup, { data } ] = useMutation(SIGNUP_MUTATION, {
	onCompleted() {
		dispatch({
          		type: 'changeAuth',
			newIsAuth: { isAuth: true }
		 })
	}
})

  const handleOnSubmit = ({ email, password }) => {
    const input = { email, password }
    signup({
	variables: { input }
    })
  }

  return (
    <UserForm  title='Sign up' onSubmit={handleOnSubmit} />
  )
}

y un archivo con las mutaciones utilizando graphql-tag. AuthMutation.js

import gql from 'graphql-tag'

export const SIGNUP_MUTATION = gql`
  mutation signup($input: UserCredentials!) {
    signup(input: $input)
  }
`

export const SIGNIN_MUTATION = gql`
  mutation signin($input: UserCredentials!) {
    signin(input: $input)
  }
`

03/06/2022 (hook, react-router-dom, @apolo/client)
src/hooks/userRegisterMutation.js:

import { gql, useMutation } from "@apollo/client";

const REGISTER = gql`
    mutation signup($input: UserCredentials!){
        signup(input: $input)
    }
`

export const useRegisterMutation = ()=> {
    const [registerMutation] = useMutation(REGISTER)

    return { registerMutation }
}

src/pages/NotRegisteredUser.js:

import React from 'react';
import Context from '../Context';
import { UserForm } from '../components/UserForm'
import { useRegisterMutation } from '../hooks/useRegisterMutation';

export const NotRegisteredUser = ()=> {
    const { registerMutation } = useRegisterMutation()

    return (
        <Context.Consumer>
            {
                ({ activateAuth })=> {
                    const onSubmit = ({ email, password }) => {
                        const input = { email, password }
                        const variables = { input }
                        registerMutation({ variables })
                            .then(activateAuth)
                    }

                    return  <>
                        <UserForm title='Registrarse' onSubmit={onSubmit} />
                        <UserForm title='Iniciar sesion' onSubmit={activateAuth} />
                    </>
                }
            }
        </Context.Consumer>
    )
}

src/components/UserForm/index.js:

import React from 'react';
import { useInputValue } from '../../hooks/useInputValue';
import { Title, Form, Input, Button } from './styles'

export const UserForm = ({ onSubmit, title })=> {
    const email = useInputValue('')
    const password = useInputValue('')

    const handleSubmit = (event)=> {
        event.preventDefault()
        onSubmit({
            email: email.value,
            password: password.value
        })
    }

    return (
        <>
            <Title>{title}</Title>
            <Form  onSubmit={handleSubmit}>
                <Input placeholder='email' {...email} />
                <Input placeholder='password' {...password} />
                <Button>{title}</Button>
            </Form>
        </>
    )
}

con todo esto de las actualizaciones que han habido en las dependencias de verdad me perd铆 en el curso, no entiendo nada de lo que se esta haciendo con graphQl y apollo

Si a ustedes el .then les marcaba error de TypeError: cannot read property .then of undefined
a pesar de haber funcionado , no encontre a que se debia este error asi que lo pase a async await.

  <RegisterMutation>
            {register => {
              const onSubmit = async ({ email, password }) => {
                const input = { email, password }
                const variables = { input }

                try {
                  await register({ variables })
                  activateAuth()
                } catch (error) {
                  console.error(error)
                }
              }
              return <UserForm onSubmit={onSubmit} title='Reg铆strate' />
            }}
          </RegisterMutation>```

Me parece que no es muy practico este curso, es mas te贸rico que practico. Gracias!!

RegisterMutation.js

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

const REGISTER = gql`
  mutation signup($input: UserCredentials!){
    signup(input: $input)
  }
`

export const useRegisterMutation = () => {
  const [mutation, { loading: mutationLoading, error: mutationError }] = useMutation(REGISTER)
  return { mutation, mutationLoading, mutationError }
}

notRegisterUser.js

import React, { useContext } from 'react'
import { UserForm } from '../components/userForm'
import { useRegisterMutation } from '../container/RegisterMutation'
import { AppContext } from '../context/AppContext'

export const NotRegisterUser = () => {
  const { activateAuth } = useContext(AppContext)
  const { mutation, mutationLoading, mutationError } = useRegisterMutation()
  if (mutationLoading) return 'Submitting...'
  if (mutationError) return `Submission error! ${mutationError.message}`
  return (
    <>
      <UserForm mutation={mutation} onSubmitForm={activateAuth} title='Registrarse' />
    </>
  )
}

userForm

export const UserForm = ({ mutation, onSubmitForm, title } 

... ... ...

  const handleSubmit = (e) => {
    const formData = new FormData(form.current)
    const formEntries = Object.fromEntries(formData)
    mutation({ variables: { input: { ...formEntries } } }).then(() => { onSubmitForm() })
    e.preventDefault()
  }


Realic茅 tambi茅n mi soluci贸n con hooks guiandome de los aportes de otros compa帽eros, pero me generaba un error.

1.- El error:

Uncaught TypeError: registerMutation is not a function

2.- NotRegisteredUser.js

import React from 'react'
import Context from '../Context'
import { UserForm } from '../components/UserForm'
import { useRegisterMutation } from '../hooks/useRegisterMutation'

export const NotRegisteredUser = () => {
  const { registerMutation } = useRegisterMutation()

  return (
    <Context.Consumer>
      {
        ({ activateAuth }) => {
          const onSubmit = ({ email, password }) => {
            console.log(email, password)
            const input = { email, password }
            const variables = { input }
            registerMutation({ variables })
              .then(activateAuth)
          }

          return (
            <>
              <UserForm title='Registrarse' onSubmit={onSubmit} />
              <UserForm title='Iniciar Sesi贸n' onSubmit={activateAuth} />
            </>
          )
        }
      }
    </Context.Consumer>
  )
}

3.- useRegisterMutation.js

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

const REGISTER = gql`
  mutation signup($input: UserCredentials!) {
    signup(input: $input)
  }
`
export const useRegisterMutation = () => {
  const [mutation] = useMutation(REGISTER)
  return { mutation }
}

4.- La soluci贸n
Quitar { } en NotRegisteredUser.js al usar el hook

const registerMutation = useRegisterMutation()

igualmente en useRegisterMutation.js al retornar

return mutation

5.- 驴Alguien sabe te贸ricamente por qu茅 esto sucede? No lo tengo muy claro

Me daba miedo que no me saliera, pero todo excelente y a la primera, me agrada aprender sobre esta aplicaci贸n

Pregunta, ese register en el <RegisterMutation> viene del servidor? o de donde sale esa funci贸n?

voy a ser sincero, el callback hell de los submit me dio dolor de cabeza tuve que repasar unas cuantas veces

Este es mi aporte de la mutaci贸n de register usando hooks.

Consulta seria posible poder gestionar el auth con un servicio como firebase en la app para gestionar los usuarios y el api en si para la app?

Les comparto mi Petgram:
https://petgram.angelozam17.now.sh/

Da el error:
Variable 鈥$input鈥 of type 鈥淯serCredentials鈥 used in position expecting type 鈥淯serCredentials!鈥."

Y no encuentro como depurar lo, alguna idea, en teor铆a todo es correcto.

Para configurar esta Mutation vamos a crear un container llamado RegisterMutation.js con el siguiente c贸digo:

import React from 鈥榬eact鈥
import { Mutation } from 鈥榬eact-apollo鈥
import { gql } from 鈥榓pollo-boost鈥

const REGISTER = gqlmutation signup ($input: UserCredentials!) { signup (input: $input) }

export const RegisterMutation = ({ children }) => {
return (
<Mutation mutation={REGISTER}>
{children}
Mutation>
)
}

Genial el curso. Lo mejor y m谩s completo que he visto.

b

Hola, les dejo mi avance hasta ahora con Nextjs:

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