¡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 “API 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 “GEOCODING API” desde la consola de donde se habilito la api “MAPS 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 ‘geometry’ 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

–save esta demas ponerlo…esta 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