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 ‘react’
import { Mutation } from ‘react-apollo’
import { gql } from ‘apollo-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 “Estilando el formulario” y antes de la clase “Controlar 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 “Register 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 “UserCredentials” used in position expecting type “UserCredentials!”."

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 ‘react’
import { Mutation } from ‘react-apollo’
import { gql } from ‘apollo-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