Si no usas la API de google por que no posees tarjeta para poder crear la facturación puedes usar esta opción
Tambie puedes obtener la lat, lng con esta otra API
https://positionstack.com/
¡Bienvenida! Este es un curso especial de React Hooks
¿Qué aprenderás en el Curso Profesional de React Hooks?
¿Qué son los React Hooks y cómo cambian el desarrollo con React?
Introducción a React Hooks
useState: estado en componentes creados como funciones
useEffect: olvida el ciclo de vida, ahora piensa en efectos
useContext: la fusión de React Hooks y React Context
useReducer: como useState, pero más escalable
¿Qué es memoization? Programación funcional en JavaScript
useMemo: evita cálculos innecesarios en componentes
useRef: manejo profesional de inputs y formularios
useCallback: evita cálculos innecesarios en funciones
Optimización de componentes en React con React.memo
Custom hooks: abstracción en la lógica de tus componentes
Third Party Custom Hooks de Redux y React Router
Configura un entorno de desarrollo profesional
Proyecto: análisis y retos de Platzi Conf Store
Instalación de Webpack y Babel: presets, plugins y loaders
Configuración de Webpack 5 y webpack-dev-server
Configuración de Webpack 5 con loaders y estilos
Loaders de Webpack para Preprocesadores CSS
Flujo de desarrollo seguro y consistente con ESLint y Prettier
Git Hooks con Husky
Estructura y creación de componentes para Platzi Conf Store
Arquitectura de vistas y componentes con React Router DOM
Maquetación y estilos del home
Maquetación y estilos de la lista de productos
Maquetación y estilos del formulario de checkout
Maquetación y estilos de la información del usuario
Maquetación y estilos del flujo de pago
Integración de íconos y conexión con React Router
Integración de React Hooks en Platzi Conf Merch
Creando nuestro primer custom hook
Implementando useContext en Platzi Conf Merch
useContext en la página de checkout
useRef en la página de checkout
Integrando third party custom hooks en Platzi Conf Merch
Configura mapas y pagos con PayPal y Google Maps
Paso a paso para conectar tu aplicación con la API de PayPal
Integración de pagos con la API de PayPal
Completando la integración de pagos con la API de PayPal
Paso a paso para conectar tu aplicación con la API de Google Maps
Integración de Google Maps en el mapa de checkout
Creando un Custom Hook para Google Maps
Estrategias de deployment profesional
Continuous integration y continuous delivery con GitHub Actions
Compra del dominio y despliega con Cloudflare
Optimización de aplicaciones web con React
Integración de React Helmet para mejorar el SEO con meta etiquetas
Análisis de performance con Google Lighthouse
Convierte tu aplicación de React en PWA
Bonus: trabaja con Strapi CMS para crear tu propia API
Crea una API con Strapi CMS y consúmela con React.js
¿Qué sigue en tu carrera profesional?
Próximos pasos para especializarte en frontend
Aún no tienes acceso a esta clase
Crea una cuenta y continúa viendo este curso
Aportes 27
Preguntas 7
Si no usas la API de google por que no posees tarjeta para poder crear la facturación puedes usar esta opción
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
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
¿Quieres ver más aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesión.