隆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?

o inicia sesi贸n.

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=鈥渂utton鈥 pero si es una etiqueta button no hace falta