¡Bienvenida! Este es un curso especial de React Hooks

1

¿Qué aprenderás en el Curso Profesional de React Hooks?

2

¿Qué son los React Hooks y cómo cambian el desarrollo con React?

Introducción a React Hooks

3

useState: estado en componentes creados como funciones

4

useEffect: olvida el ciclo de vida, ahora piensa en efectos

5

useContext: la fusión de React Hooks y React Context

6

useReducer: como useState, pero más escalable

7

¿Qué es memoization? Programación funcional en JavaScript

8

useMemo: evita cálculos innecesarios en componentes

9

useRef: manejo profesional de inputs y formularios

10

useCallback: evita cálculos innecesarios en funciones

11

Optimización de componentes en React con React.memo

12

Custom hooks: abstracción en la lógica de tus componentes

13

Third Party Custom Hooks de Redux y React Router

Configura un entorno de desarrollo profesional

14

Proyecto: análisis y retos de Platzi Conf Store

15

Git Hooks con Husky

16

Instalación de Webpack y Babel: presets, plugins y loaders

17

Configuración de Webpack 5 y webpack-dev-server

18

Configuración de Webpack 5 con loaders y estilos

19

Loaders de Webpack para Preprocesadores CSS

20

Flujo de desarrollo seguro y consistente con ESLint y Prettier

Estructura y creación de componentes para Platzi Conf Store

21

Arquitectura de vistas y componentes con React Router DOM

22

Maquetación y estilos del home

23

Maquetación y estilos de la lista de productos

24

Maquetación y estilos del formulario de checkout

25

Maquetación y estilos de la información del usuario

26

Maquetación y estilos del flujo de pago

27

Integración de íconos y conexión con React Router

Integración de React Hooks en Platzi Conf Merch

28

Creando nuestro primer custom hook

29

Implementando useContext en Platzi Conf Merch

30

useContext en la página de checkout

31

useRef en la página de checkout

32

Integrando third party custom hooks en Platzi Conf Merch

Configura mapas y pagos con PayPal y Google Maps

33

Paso a paso para conectar tu aplicación con la API de PayPal

34

Integración de pagos con la API de PayPal

35

Completando la integración de pagos con la API de PayPal

36

Paso a paso para conectar tu aplicación con la API de Google Maps

37

Integración de Google Maps en el mapa de checkout

38

Creando un Custom Hook para Google Maps

Estrategias de deployment profesional

39

Continuous integration y continuous delivery con GitHub Actions

40

Compra del dominio y despliega con Cloudflare

Optimización de aplicaciones web con React

41

Integración de React Helmet para mejorar el SEO con meta etiquetas

42

Análisis de performance con Google Lighthouse

43

Convierte tu aplicación de React en PWA

Bonus: trabaja con Strapi CMS para crear tu propia API

44

Crea una API con Strapi CMS y consúmela con React.js

¿Qué sigue en tu carrera profesional?

45

Próximos pasos para especializarte en frontend

No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

useRef en la página de checkout

31/45
Recursos

Aportes 15

Preguntas 9

Ordenar por:

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

Dejo como complemento este paquete que nos ayuda a construir formularios: https://react-hook-form.com/

Aunque Oscar para regresar de information a la página checkout ha usado el componente <Link> de React Router, lo ideal seria sacarle el máximo partido que podamos a las rutas.

Dentro de los componentes que renderizamos a través de Route existen en sus props un objeto llamado history, el cual podemos usar para regresar a la página anterior, ya que la app es una secuencia podemos usarla.

props.history.goBack()

Todas estas propiedades las explica Leonidas en el curso de React-Router

https://platzi.com/clases/1342-react-router/12868-manipulando-el-historial/

Una manera mas facil de crear el objeto en la constante buyer es:

  function handleSubmit() {
    const formData = new FormData(form.current);
    const buyer = Object.fromEntries(formData);
    console.log(buyer);
  }

Con esto nos ahorramos tener que escribir el objeto de forma literal, y además nos ahorramos mucho código.

Si estas usando el plugin de prettier en VS, y la parte del buyer le quita las comillas, puedes poner un comentario para que no formaté el codigo, asi,

  const handleSubmit = () => {
    const formData = new FormData(form.current);
    // prettier-ignore
    const buyer = {
      'name': formData.get('name'),
      'email': formData.get('email'),
      'address': formData.get('address'),
      'apto': formData.get('apto'),
      'city': formData.get('city'),
      'country': formData.get('country'),
      'state': formData.get('state'),
      'cp': formData.get('cp'),
      'phone': formData.get('phone'),
    };
    addToBuyer(buyer);
  };

Amigos yo lo hice creándome un custom hook useForm pero no se no se si la mejor forma de hacerlo
useForm.js

InformationScreen.jsx

constante buyer:

const buyer = {
      'name': formData.get('name'),
      'email': formData.get('email'),
      'address': formData.get('address'),
      'apto': formData.get('apto'),
      'city': formData.get('city'),
      'country': formData.get('country'),
      'state': formData.get('state'),
      'cp': formData.get('cp'),
      'phone': formData.get('phone'),
    }

pueden agregar esta linea en el webbpack.config.js para que el navegador se refresque y puedan hacer debug en el navegador

mode: 'development',

Aqui el codigo con la solicion del bug el momento de eliminar items de la lista.

useInitialState.js

import { useState } from 'react';
import initialState from '../initialState';

const useInitialState = () => {
  const [state, setState] = useState(initialState);

  const addToCart = (payload) => {
    setState({
      ...state,
      cart: [...state.cart, payload],
    });
  };

  const removeFromCart = (payload, indexToRemove) => {
    setState({
      ...state,
      cart: state.cart.filter((_items, indexCurrent) => indexCurrent !== indexToRemove),
    });
  };

  return {
    addToCart,
    removeFromCart,
    state,
  };
};

export default useInitialState;

Checkout.jsx

import React, { useContext } from 'react';
import { Link } from 'react-router-dom';
import AppContext from '../context/AppContext';
import '../styles/components/Checkout.css';

const Checkout = () => {
  const { state, removeFromCart } = useContext(AppContext);
  const { cart } = state;

  const handleRemove = (product, index) => () => {
    removeFromCart(product, index);
  };

  const handleSumTotal = () => {
    const reducer = (accumulator, currentValue) => accumulator + currentValue.price;
    const sum = cart.reduce(reducer, 0);
    return sum;
  };

  return (
    <div className='Checkout'>
      <div className='Checkout-content'>
        {cart.length > 0 ? <h3>Lista de pedidos:</h3> : <h3>Sin pedidos...</h3>}
        {cart.map((item, index) => (
          <div className='Checkout-item'>
            <div className='Checkout-element'>
              <h4>{item.title}</h4>
              <span>
                $
                {item.price}
              </span>
            </div>
            <button type='button' onClick={handleRemove(item, index)}>
              <i className='fas fa-trash-alt' />
            </button>
          </div>
        ))}
      </div>
      {cart.length > 0 && (
        <div className='Checkout-sidebar'>
          <h3>{`Precio Total: $ ${handleSumTotal()}`}</h3>
          <Link to='/checkout/information'>
            <button type='button'>Continuar pedido</button>
          </Link>
        </div>
      )}
    </div>
  );
};

export default Checkout;
 

Aqui el commit de la clase en Typescript:

  • Asigne buyer como objeto puesto tengo intenciones de hacerlo unico en Login status.
    -Hay un error en useInitialize linea 42, no se muestra en vsc pero si en el tsc. Si descubren porque se da y como solventarlos les agradeceria la collab.
    Chromerce

Algo que hice en nuestro useInitial state fue agregar un useEffect que detecte cada vez que cambie nuestro carrito y lo re-ordene en orden alfabetico, de esta forma cuando obtenemos nuestros productos en el checkout o en la pagina de information siempre los productos iguales van a estar juntos aunque se hayan agregado en otro orden

import { useEffect, useState } from "react";
import initialState from "../initialState";

export default function useInitialState() {
   const [state, setState] = useState(initialState);

   // Using a useEffect to always re-sort our cart when it's updated
   useEffect(() => {
      const sortedCart = state.cart.sort((item, prevItem) => item.title > prevItem.title ? 1 : -1);
      setState({...state, cart: sortedCart});
   }, [state.cart]);

   const addToCart = payload => {
      // Assigning first a unique cart id to be able to delete only that element in the future
      const randomNumber = Math.floor(Math.random() * Date.now());
      const newItem = {...payload, cartId: `${payload.id}-${randomNumber}`};

      setState({
         ...state,
         cart: [...state.cart, newItem]
      });
   };
   const removeFromCart = payload => {
      setState({
         ...state,
         cart: state.cart.filter(item => item.cartId !== payload.cartId)
      });
   };

   const addToBuyer = payload => {
      setState({
         ...state,
         buyer: payload
      });
   };

   return {
      addToCart,
      removeFromCart,
      addToBuyer,
      state
   };
}

Aqui pueden ver como no importa en que orden agrege los articulos siempre salen acomodados en orden alfabetico

Con react 18 podemos hacer la navegación hacia atras con un hook de router

import {useNavigate} from 'react-router-dom';

Y podemos gacer una función paraceida a esta:

  const handleClick = () => {
    navigate('/checkout');
  };

Y solo la llamamos en el onclick del elemento

Aporte codigo utilizado durante la clase:
.
src/containers/containers/Information

import React, { useRef, useContext} from "react";
import '../styles/components/Information.css';
import { Link } from "react-router-dom";
import AppContext from "../context/AppContext";
const Information = ()=>{
    const { state, addToBuyer } = useContext(AppContext);
    const form = useRef(null);

    const { cart } = state;

    const handlerSubmit = () =>{
        const formData = new FormData(form.current);
        const buyer = {
            'name': formData.get('name'),
            'email': formData.get('email'),
            'address': formData.get('address'),
            'apto': formData.get('apto'),
            'city': formData.get('city'),
            'country': formData.get('country'),
            'state': formData.get('state'),
            'cp': formData.get('cp'),
            'phone': formData.get('phone'),
        }
        addToBuyer(buyer);
    }

    return (
    <div className="Information">
        <div className="Information-content">
            <div className="Information-head">
                <h2>Información de contacto:</h2>
            </div>
            <div className="Information-form">
                <form ref={form}>
                    <input type="text" placeholder="Nombre completo" name="name" />
                    <input type="text" placeholder="Correo Electronico" name="email" />
                    <input type="text" placeholder="Direccion" name="addres" />
                    <input type="text" placeholder="apto" name="apto" />
                    <input type="text" placeholder="Ciudad" name="city" />
                    <input type="text" placeholder="Pais" name="country" />
                    <input type="text" placeholder="Estado" name="state" />
                    <input type="text" placeholder="Codigo postal" name="cp" />
                    <input type="text" placeholder="Telefono" name="phone" />
                </form>
            </div>
            <div className="Information-buttons">
                
                <div className="Information-back">
                    <Link to="/checkout">
                        Regresar
                    </Link>
                </div>
                <div className="Information-next">
                    <button onClick={handlerSubmit} type="button">pagar</button>
                </div>
                
            </div>
        </div>
        <div className="Information-sidebar">
            <h3>Pedido:</h3>
            {cart.map(item=>(
                <div key={item.title} className="Information-item">
                    <div className="Information-element">
                        <h4>{item.title}</h4>
                        <span>${item.price}</span>
                    </div>
                </div>
            ))}
            
        </div>
    </div>
    )
}
export default Information;

src/hooks/useInitialState.js

import { useState } from "react";
import initialState from "../initialState";


const useInitialState = ()=>{
    const [state, setState] = useState(initialState);
    
    const addToCart = payload =>{
        setState({
            ...state,
            cart:[...state.cart,payload]
        });
    }

    const removeFromCart = payload =>{
        setState({
            ...state,
            cart:state.cart.filter(item=>item.id!==payload.id)
        })
    }

    const addToBuyer = payload=>{
        setState({
            ...state,
            buyer:[...state.buyer, payload]
        })
    }

    return {
        addToBuyer,
        addToCart,
        removeFromCart,
        state,
    }
};

export default useInitialState;

src/initialState.js

export default {
    cart: [],
    buyer:[],
    products: [
        {
        'id': '1',
        'image': 'https://arepa.s3.amazonaws.com/camiseta.png',
        'title': 'Camiseta',
        'price': 25,
        'description': 'Lorem ipsum dolor sit amet, consectetur adipiscing elit',
        },
        {
        'id': '3',
        'image': 'https://arepa.s3.amazonaws.com/mug.png',
        'title': 'Mug',
        'price': 10,
        'description': 'Lorem ipsum dolor sit amet, consectetur adipiscing elit',
        },
        {
        'id': '4',
        'image': 'https://arepa.s3.amazonaws.com/pin.png',
        'title': 'Pin',
        'price': 4,
        'description': 'Lorem ipsum dolor sit amet, consectetur adipiscing elit',
        },
        {
        'id': '5',
        'image': 'https://arepa.s3.amazonaws.com/stickers1.png',
        'title': 'Stickers',
        'price': 2,
        'description': 'Lorem ipsum dolor sit amet, consectetur adipiscing elit',
        },
        {
        'id': '6',
        'image': 'https://arepa.s3.amazonaws.com/stickers2.png',
        'title': 'Stickers',
        'price': 2,
        'description': 'Lorem ipsum dolor sit amet, consectetur adipiscing elit',
        },
        {
        'id': '7',
        'image': 'https://arepa.s3.amazonaws.com/hoodie.png',
        'title': 'Hoodie',
        'price': 35,
        'description': 'Lorem ipsum dolor sit amet, consectetur adipiscing elit',
        },
    ],
};

Implemente el formulario con React Hook Form y es increíble lo fácil que se torna manipular el mismo

Al boton de pagar, si fuera un tag input le tenes que poner type=“button” pero si es una etiqueta button no hace falta