隆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

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

16

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

17

Configuraci贸n de Webpack 5 con loaders y estilos

18

Loaders de Webpack para Preprocesadores CSS

19

Flujo de desarrollo seguro y consistente con ESLint y Prettier

20

Git Hooks con Husky

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

A煤n no tienes acceso a esta clase

Crea una cuenta y contin煤a viendo este curso

Creando un Custom Hook para Google Maps

38/45
Recursos

Aportes 27

Preguntas 7

Ordenar por:

驴Quieres ver m谩s aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesi贸n.

Si no usas la API de google por que no posees tarjeta para poder crear la facturaci贸n puedes usar esta opci贸n

https://react-leaflet.js.org/

Tambie puedes obtener la lat, lng con esta otra API
https://positionstack.com/

Si alguien le sale este error



Lo solucione agregando esto a babel

npm install --save @babel/runtime 
npm install --save-dev @babel/plugin-transform-runtime

Y colocando en el archivo .babelrc

{
  "presets": [
    "@babel/preset-env",
    "@babel/preset-react"
  ],
  "plugins": [
    ["@babel/transform-runtime"]
  ]
}

Les recomiendo que restrinjan su API_KEY si usan las APIs de Google en producci贸n. Lo pueden hacer desde la consola de Google Cloud Platform en 鈥淎PI y Servicios/ Credenciales鈥 y seleccionando su API_KEY. Pueden restringirla por URL o por IP y as铆 evitar que alguien no deseado use su API_KEY y les empiece a facturar.

Si buyer name les aparece undefined, recuerden que buyer es un arreglo. utilicen:

 <h2>{`${buyer[0].name}, Gracias por tu compra`}</h2>

Recuerden que deben habilitar Geocoding API en su proyecto. https://console.cloud.google.com/

le falto decir que hay que habilidar la api 鈥淕EOCODING API鈥 desde la consola de donde se habilito la api 鈥淢APS JAVASCRIPT API鈥 como se van olvidar de detalles tan importantes, por cosas como estas es que no renuevo la suscripci贸n, hay que estar complementando con investigaci贸n en google, preferiblemente se investiga en google los temas que se quieran estudiar y es mejor.

Para los que no desean registrar su tarjeta, aca esta un mock del JSON que responde la api.

{
   "results" : [
      {
         "address_components" : [
            {
               "long_name" : "1600",
               "short_name" : "1600",
               "types" : [ "street_number" ]
            },
            {
               "long_name" : "Amphitheatre Pkwy",
               "short_name" : "Amphitheatre Pkwy",
               "types" : [ "route" ]
            },
            {
               "long_name" : "Mountain View",
               "short_name" : "Mountain View",
               "types" : [ "locality", "political" ]
            },
            {
               "long_name" : "Santa Clara County",
               "short_name" : "Santa Clara County",
               "types" : [ "administrative_area_level_2", "political" ]
            },
            {
               "long_name" : "California",
               "short_name" : "CA",
               "types" : [ "administrative_area_level_1", "political" ]
            },
            {
               "long_name" : "United States",
               "short_name" : "US",
               "types" : [ "country", "political" ]
            },
            {
               "long_name" : "94043",
               "short_name" : "94043",
               "types" : [ "postal_code" ]
            }
         ],
         "formatted_address" : "1600 Amphitheatre Parkway, Mountain View, CA 94043, USA",
         "geometry" : {
            "location" : {
               "lat" : 37.4224764,
               "lng" : -122.0842499
            },
            "location_type" : "ROOFTOP",
            "viewport" : {
               "northeast" : {
                  "lat" : 37.4238253802915,
                  "lng" : -122.0829009197085
               },
               "southwest" : {
                  "lat" : 37.4211274197085,
                  "lng" : -122.0855988802915
               }
            }
         },
         "place_id" : "ChIJ2eUgeAK6j4ARbn5u_wAGqWA",
         "plus_code": {
            "compound_code": "CWC8+W5 Mountain View, California, United States",
            "global_code": "849VCWC8+W5"
         },
         "types" : [ "street_address" ]
      }
   ],
   "status" : "OK"
}

Les comparto de c贸mo quedaron los archivos y c贸mo los tuve que modificar:
En primer lugar, tom茅 los passwords y los volv铆 un objeto:

const pass = {
  paypalPaymentClientID : 'your_paypalPaymentClientID',
  googleMapsAPI : 'your_googleMapsAPI',
}

export default pass;

Cuando ya tengo los passwords para ser exportados, en el file de .gitignore lo agrego en d贸nde lo tengo, que en mi caso es la ra铆z del proyecto, y as铆 nunca lo env铆o y lo mantengo solo en mi PC. No es seguro sin embargo, pero no expongo los datos y a qui茅n le sirva, se puede guiar de c贸mo lo realic茅.
路 路 路
Para el useGoogleAddress, lo resolv铆 gracias a separar el scope de las funciones, haciendo, una funci贸n para traer datos de coordenadas y devolviendo esa consulta en una variable que luego utilizo dentro del useEffect para que e ejecute as铆ncronamente y se pase a map

// useGoogleAddress.js

import { useState, useEffect } from 'react';
import axios from 'axios';
import pass from '../../pass';

const getCoordinates = async (api) => {
  const response = await axios(api);
  return response
}

const useGoogleAddress = address => {
  const [map, setMap] = useState({});
  const API_KEY = pass.googleMapsAPI;
  const API = `https://maps.googleapis.com/maps/api/geocode/json?address=${address}&key=${API_KEY}`;
  
  useEffect( async () => {
    const res = await getCoordinates(API);
    setMap(res.data.results[0].geometry.location);
  }, []);

  return map;
}

export default useGoogleAddress;

路 路 路

// Success.js

import React, { useContext } from 'react';
import AppContext from '../context/AppContext';
import Map from '../components/Map';
import useGoogleAddress from '../hooks/useGoogleAddress';
import '../styles/containers/Success.scss';

const Success = () => {
  const { state } = useContext(AppContext);
  const { buyer } = state;
  const location = useGoogleAddress(buyer[0].address);

  return (
    <div className="Success">
      <div className="Success-content">
        <h2>
          {`${buyer[0].name}, gracias por invertir en nosotros`}
        </h2>
        <span>Tu pedido llegara en 2 d铆as a tu direcci贸n</span>
        <div className="Success-map">
          <Map data={location} />
        </div>
      </div>
    </div>
  );
}

export default Success;
// Map.js

import React from 'react'
import{ GoogleMap, LoadScript, Marker } from '@react-google-maps/api';
import pass from '../../pass';

const API_KEY = pass.googleMapsAPI;

const Map = ({data}) => {
  const containerStyle = {
    width: '100%',
    height: '50vh',
  }
  const center = {
    lat: data.lat, lng: data.lng,
  }
  
  return (
    <LoadScript googleMapsApiKey={API_KEY}>
      <GoogleMap
        mapContainerStyle={containerStyle}
        zoom={17}
        center={center}
      >
        <Marker position={center} />
      </GoogleMap>
    </LoadScript>
  )
}

export default Map

Tengo que aclarar que no fue f谩cil y que tard茅 haciendo que todo me funcione. Pues el c贸digo que nos dej贸 el profesor a m铆 no me funcion贸 y lo modifiqu茅 para ello.

Tambi茅n que aclarar lo realizado en el servicio de cloud de google para las API de maps y geolocalizaci贸n por coordenadas: SOLICIT脡 UN SALDO GRATIS QUE OFRECE GOOGLE, PERO TUVE QUE PONER UNA TARJETA DE CR脡DITO. AH脥 DICEN C脫MO NO TE VAN A COBRAR POR USAR TODO, LEE POR FAVOR.

Espero sus comentarios.

Me pide poner mi tarjeta para poder usar google maps

Creo que se deber铆a usar otra api en vez de Google maps

Bueno, despues de quemarme las pesta帽as por un buen par de horas para que las direcciones sean m谩s precisas, llegu茅 a esta soluci贸n, la cual no se si est谩 del todo bien, pero funciona:

// useGoogleAddress.js

const useGoogleAddress = (address, city, province, country) => {
  const [map, setMap] = useState({});
  const API = `https://maps.googleapis.com/maps/api/geocode/json?address=${address}${city}${province}${country}&key=${process.env.REACT_APP_API_KEY}`;

Ac谩 le paso varios par谩metros, porque solamente con address me mandaba a alguna parte de Europa.
.
Prosiguiendo, cuando renderizo el componente Map.jsx en el container Success.jsx le paso lo siguiente:

const Success = () => {
  const { state } = useContext(AppContext);
  const { buyer } = state;
  
// Esto necesito destructurarlo pero no s茅 c贸mo, estar铆a genial que alguien me ayude
  const buyerLocation = useGoogleAddress(
    buyer[0].address,
    buyer[0].city,
    buyer[0].province,
    buyer[0].country
  ); 

  return (
    <div className="Succes">
      <div className="Success-content">
        <h2>{`Thanks for your Order, ${buyer[0].name}!`}</h2>
        <span>It will come to you within 3 days from now on.</span>

        <div className="Success-map">
          <Map data={buyerLocation} />
        </div>
      </div>
    </div>
  );
};

Y el Map.jsx queda as铆:

const Map = ({ data }) => {
  const mapStyles = {
    height: '50vh',
    width: '100%',
  };

  const defaultCenter = {
    lat: data.lat,
    lng: data.lng,
    // this throws console errors. Is it because async functions?
  };

  console.log(defaultCenter);

  return (
    <LoadScript googleMapsApiKey={process.env.REACT_APP_API_KEY}>
      <GoogleMap mapContainerStyle={mapStyles} zoom={9} center={defaultCenter}>
        <Marker position={defaultCenter} />
      </GoogleMap>
    </LoadScript>
  );
};

El problema es que me tira el siguiente error cuando llego al Success:

Supongo que se debe al llamado as铆ncrono a la API, porque primero los valores de las coordenadas aparecen undefined y despu茅s agarran su verdadero valor. Si a alguien le paso lo mismo, comparta su soluci贸n.
Un saludo compa帽eros! y perd贸n por lo extenso

Es muy probable que le salga este error馃憞:

Ntp, se resulve con tan solo inicializar el estado:

const [map, setMap] = React.useState({lat: 0, lng: 0});

Por fin!

En mi caso no me renderizaba el mapa y era porque no habia asociado una tarjeta con google (no te cobran nada), luego segu铆 los mismos pasos que Oscar y me funcion贸.

Lo que si olvidan decir es que hay que activar la API
Geocoding API en la consola o Google Maps Platform.

al finalizar la compra podemos vaciar el carrito usando:

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

en useInitialState.js

Me sale este error y me dej贸 ciego. A alguien le pas贸?

Uncaught (in promise) TypeError: Cannot read property 鈥榞eometry鈥 of undefined

No manden async () => {} como parametro del useEffect.

Warning: An effect function must not return anything besides a function, which is used for clean-up.

It looks like you wrote useEffect(async () => 鈥) or returned a Promise. Instead, write the async function inside your effect and call it immediately:

Esto pasa porque cuando usamos la keyword async antes de la declaracion de la funcion lo que retorna es en si una Promise. Mas info

鈥搒ave esta demas ponerlo鈥sta por defecto

No olviden activar el servicio de Maps y geoCode en su google panel

https://locationiq.com

Una alternativa a Geocoding API de Google

Una forma de usar async await dentro de useEffect, pues react recomiendo no enviarle un async funcion de forma directa

import { useState, useEffect } from "react";
import axios from "axios";

const useGoogleAddress = address => {
    const [map, setMap] = useState({});
    const API = `https://maps.googleapis.com/maps/api/geocode/json?address=${address}&key=${API_KEY}`;

    useEffect(() => {
        async function handler() {
            const response = await axios(API);
            setMap(response.data.results[0].geometry.location);
        }
        handler();
    }, []);
    return map;
};

export default useGoogleAddress;

Pues yo tengo problemas con la API de paypal, ni con datos reales ni con datos falsos funciona 馃槙

Despu茅s de luchar para encontrar las API que deb铆a habilitar en mi cuenta de Google, me aparece el 煤ltimo mensaje:

{
error_message: "You must enable Billing on the Google Cloud Project at https://console.cloud.google.com/project/_/billing/enable Learn more at https://developers.google.com/maps/gmp-get-started",
results: [ ],
status: "REQUEST_DENIED"
}

:;D:D:D;DD;DDDDDDD

En este caso seria m谩s conveniente en ves de:

const location = useGoogleAddress(buyer[0].address);

es mejor as铆 ya que el otro setea el primero y no el m谩s reciente:

const location = useGoogleAddress(buyer[buyer.length - 1].address);

Es necesario que en la consola de google agreguen la API de Geocoding para obtener su API KEY, despu茅s ya pueden pasar el par谩metro y agregan al final su API KEY.

Porque utilizar axios y no fetch? o solo es por gusto?

La variable address que se le asigna el hook de useGoogleAddress deber铆a llamarse esa funci贸n en un useEffect. Ya que si no estoy mal cada que se actualice el estado de esa secci贸n se llamara esa API cada refresh de react.

b