DEV Community

Cover image for Building an Autocomplete Address Form in React ๐Ÿ—บ๏ธ๐Ÿ“
Florian for ExoAPI

Posted on • Originally published at exoapi.dev

Building an Autocomplete Address Form in React ๐Ÿ—บ๏ธ๐Ÿ“

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
Enter fullscreen mode Exit fullscreen mode

Now, let's install additional dependencies to use Google Maps API:

npm install react-geocode
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

โš ๏ธ 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;
Enter fullscreen mode Exit fullscreen mode

Run your app:

npm start
Enter fullscreen mode Exit fullscreen mode

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);
  }
};
Enter fullscreen mode Exit fullscreen mode

โš ๏ธ 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
Enter fullscreen mode Exit fullscreen mode

And remove the following lines:

// These lines are not needed anymore when using ExoAPI
import { setDefaults, fromLatLng } from "react-geocode";

setDefaults({
  key: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
});
Enter fullscreen mode Exit fullscreen mode

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)