As developers, creating a seamless user experience is crucial, especially when it comes to forms. Autocompleting address fields can significantly enhance the user interaction by reducing input errors and speeding up the form-filling process. In this article, we'll walk through the steps to create a React address form component that leverages a reverse geocoding API. We'll use the Google Maps API as an example, and then explore an affordable alternative using ExoAPI.
Prerequisites
Before we dive into coding, make sure you have Node.js and npm installed on your machine. You'll also need a basic understanding of React.
Setting up the React App
Start by creating a new React app using Create React App:
npx create-react-app address-form-app
cd address-form-app
Now, let's install additional dependencies to use Google Maps API:
npm install react-geocode
Reverse Geocoding
When requesting the current location from devices like computers or smartphones, we only get geographic coordinates in the form of latitude and longitude numbers. To get the actual address in a human-readable form with street name, city, postcode and country, we need to use a process called reverse geocoding.
Reverse geocoding is the transformation of coordinates (latitude and longitude) into a human-readable address. It works by looking up the address in a giant database of coordinates, which is why we need to use an API to query that information.
Option A - Using Google Maps API
โ ๏ธ If using Google APIs is not an option for you, we'll offer an simpler and cheaper alternative below using ExoAPI.
1. Get an API Key
Go to the Google Cloud Console, create a new project, and enable the "Geocoding API" for your project. Generate an API key.
2. Create the AddressForm Component
Create a new file AddressForm.js
in the src
folder:
// src/AddressForm.js
import { useState } from "react";
import { setDefaults, fromLatLng } from "react-geocode";
setDefaults({
// Put your Google Maps API key here:
key: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
});
const AddressForm = () => {
const [addressComponents, setAddress] = useState({
street: "",
city: "",
postcode: "",
country: "",
// Add more fields as needed
});
const useCurrentLocation = async () => {
if (!navigator.geolocation) {
console.error("Geolocation is not supported by this browser.");
return;
}
try {
// 1. Request current position from device
const position = await new Promise((resolve, reject) => navigator.geolocation.getCurrentPosition(resolve, reject));
const { latitude, longitude } = position.coords;
// 2. Query the reverse geocoding API
const address = await fromLatLng(latitude, longitude);
console.log("[useCurrentLocation]", { latitude, longitude, address });
// 3. Extract address components from Google Maps API response
const components = address.results[0]?.address_components.reduce((acc, component) => {
acc[component.types[0]] = component.long_name;
return acc;
}, {});
// 4. Autocomplete form
setAddress({
street: [components.route, components.street_number].filter((x) => x).join(" "),
city: components.locality || components.administrative_area_level_1 || "",
postcode: components.postal_code || "",
country: components.country || "",
});
} catch (error) {
console.error("Error:", error);
}
};
return (
<div>
<h2>Address Form</h2>
<form>
<label>
Street:
<input type="text" value={addressComponents.street} onChange={(e) => setAddress({ ...addressComponents, street: e.target.value })} />
</label>
<br />
<label>
City:
<input type="text" value={addressComponents.city} onChange={(e) => setAddress({ ...addressComponents, city: e.target.value })} />
</label>
<br />
<label>
Postcode:
<input type="text" value={addressComponents.postcode} onChange={(e) => setAddress({ ...addressComponents, postcode: e.target.value })} />
</label>
<br />
<label>
Country:
<input type="text" value={addressComponents.country} onChange={(e) => setAddress({ ...addressComponents, country: e.target.value })} />
</label>
<br />
<button type="button" onClick={useCurrentLocation}>
Use current location
</button>
</form>
</div>
);
};
export default AddressForm;
โ ๏ธ Don't forget to add your Google Maps API key to this file before continuing.
3. Use the AddressForm Component
Now, you can use the AddressForm
component in your src/App.js
:
// src/App.js
import AddressForm from "./AddressForm";
function App() {
return (
<div className="App">
<AddressForm />
</div>
);
}
export default App;
Run your app:
npm start
Visit http://localhost:3000 in your browser, you should see the Address Form with autocomplete.
Option B - Using ExoAPI
ExoAPI offers an affordable and easy-to-use alternative to Google Maps API (and it's 96% cheaper! ๐ค):
1. Sign Up for ExoAPI
Visit ExoAPI and sign up for an account to obtain your API key.
2. Update the AddressForm Component
In AddressForm.js
, replace the useCurrentLocation
function to use ExoAPI:
const useCurrentLocation = async () => {
if (!navigator.geolocation) {
console.error("Geolocation is not supported by this browser.");
return;
}
try {
// 1. Request current position from device
const position = await new Promise((resolve, reject) => navigator.geolocation.getCurrentPosition(resolve, reject));
const { latitude, longitude } = position.coords;
// 2. Query the reverse geocoding API
const address = await (
await fetch("https://api.exoapi.dev/reverse-geocoding", {
method: "POST",
headers: {
Authorization: "Bearer <your-api-key>",
"Content-Type": "application/json",
},
body: JSON.stringify({ lat: latitude, lon: longitude, locale: "en-GB" }),
})
).json();
console.log("[useCurrentLocation]", { latitude, longitude, address });
// 3. Autocomplete form
setAddress({
street: [address.street, address.houseNumber].filter((x) => x).join(" "),
city: address.city || "",
postcode: address.postalCode || "",
country: address.country || "",
});
} catch (error) {
console.error("Error:", error);
}
};
โ ๏ธ Don't forget to replace <your-api-key>
with the API key you obtained from ExoAPI.
3. Remove Google Maps dependencies
ExoAPI works without any external dependencies, so you can uninstall the Google Maps module:
npm uninstall react-geocode
And remove the following lines:
// These lines are not needed anymore when using ExoAPI
import { setDefaults, fromLatLng } from "react-geocode";
setDefaults({
key: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
});
Conclusion
Congratulations! ๐ You now have a flexible React Address Form component that can work with either the Google Maps API or ExoAPI for reverse geocoding. Choose the option that best fits your project requirements and preferences.
Top comments (0)