Adding Address Autocomplete to Medusa.js Checkout
Tags: medusa, react, addressautocomplete, ecommerce
Published: 2022-05-27 19:02:33

[Medusa.js](https://medusajs.com/) is an open-source Shopify alternative built with JavaScript. It’s a great solution if you’re looking for a customizable ecommerce solution.

In this tutorial, we’ll see how to add [Lob’s Address Autocomplete API](https://www.lob.com/address-verification) feature to a Medusa project to give customers a faster checkout process.

You can find the complete code in this [GitHub repo](https://github.com/lob/medusa-next-address-autocomplete).


## Why use address autocomplete?		

Every bit of extra information that customers must enter in the checkout process adds to the likelihood of cart abandonment.		

The information that takes the longest is undoubtedly the shipping address.

By using Lob’s Address Autocomplete API we can not only save time for customers but also validate addresses to reduce the possibility of errors.				


## Installing Medusa				

In this tutorial, we’ll add the Lob Autocomplete React component to the checkout form found in the Medusa Next.js starter template.		

To begin, you’ll need to install these two repos: 

* [medusa-starter-default](https://github.com/medusajs/medusa-starter-default) which is the Medusa server. (Do NOT seed your database yet)
* [medusa-nextjs-starter](https://github.com/medusajs/nextjs-starter-medusa) which is the Next.js frontend template.		

You’ll find the installation instructions in the respective repos so we won’t repeat them here for the sake of brevity.

After installing, make sure you run the dev server on both projects (which run on ports 8000 and 9000 by default).							


## Set up Medusa for the US market

This walkthrough is designed for a US Storefront—though Lob has [International Autocomplete](https://docs.lob.com/#operation/intl_autocompletions) support and could be used for non-US storefronts. We will need to make three adjustments so you get US dollars (USD) instead of Euros displayed in our starter store.


### Seeding our store database

In your Medusa store project, open _`my-medusa-store/data/seed.json`_.

Swap the order of the regions, so NA (North America) is first, and therefore the default.

{% gist https://gist.github.com/lobot/2b60afcec0c62030f3cd0e1840a2a567.js %}

To seed your Medusa store run the following command:

{% gist https://gist.github.com/lobot/3bc45eae2662dcd632de242b744ebff6.js %}


### Setting currency to USD			

The default currency of the Next template is set to EUR. Let’s change that to USD as Lob’s autocomplete API generates US addresses while in test mode.					

To do this, go to the frontend project (all our customizations will apply to the frontend) and change the `currencyCode` property to "_usd_" in the file context/store-context.js.
			
_context/store-context.js_
{% gist https://gist.github.com/lobot/54640a6ceb9649eb9b05e1b1b560e016.js %}

We’ll also need to change the default display from EUR to USD which we can do in the file components/checkout/shipping-method.jsx.
									
_components/checkout/shipping-method.jsx_

{% gist https://gist.github.com/lobot/061f9411c99a11ee56e5e3d967eae756.js %}


## Adding autocomplete							

The default checkout page of the Medusa store currently looks like this:


![default checkout page](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9lcvw2d8knd50zuqb6ff.png)

Our approach to adding address autocomplete will be:

1. Replace the “Address 1” field with the Lob autocomplete React component.

2. Add a “State” field (Medusa doesn’t provide this by default and it’s needed for US addresses).

3. When an address is selected through the autocomplete, programmatically fill the country, city, state, and postal code fields.

With this done, filling out the address form will be significantly faster—users only need to type a few characters to get a full address.	


## Creating address field component

The main component for the checkout form is in the file _`components/checkout/information-step.jsx`_. This is where you’ll find the address input that we’re going to replace with the address autocomplete component.						
Let’s first make a copy of the _`input-field`_ component and customize it to include the autocomplete. By doing it this way, we can keep the wrapper for error handling that is already present in the _`input-field`_.
									
To do this, go to the terminal and copy the _`input-field`_ component to a new component _`address-field`_:

{% gist https://gist.github.com/lobot/a46a6f131dc0bd0184d5a5cb2425d5d1.js %}

In the new component file, rename the exported function from _`InputField`_ to _`AddressField`_.

_components/checkout/address-field.jsx_
{% gist https://gist.github.com/lobot/f99199e255d2c00b1f73224e34f2689c.js %}


## Adding autocomplete component				

We’re now going to install Lob’s React address autocomplete component which provides a ready-to-use autocomplete, saving us from having to implement one from scratch.								

Let’s first go to the terminal and install it with NPM. We add @previous so the component supports React 17 which is compatible with the Medusa starter project.

{% gist https://gist.github.com/lobot/ee93607aa1d21073421f8560019353aa.js %}

To use the autocomplete API, we’ll need a Lob API key. The instructions for generating one are [outlined here](https://github.com/lob/react-address-autocomplete#getting-api-keys).

Grab the publishable test key and add it to your .env.local file. We’ll use a variable name _`NEXT_PUBLIC_LOB_PUBLISHABLE_KEY`_. By prefixing it with _NEXT_PUBLIC__ we can make it accessible from the frontend source code.

_.env.local_
{% gist https://gist.github.com/lobot/b63bd1ec6b46c0b499a9a9a20a56dce7.js %}

Now, open the component file _`components/checkout/address-field.jsx`_ and import the Autocomplete component at the top of the file under the existing imports.					
Then, create a variable apiKey and assign to it your publishable Lob API key. 

_components/checkout/address-field.jsx_
{% gist https://gist.github.com/lobot/3ecdcc51638f173d622e79e25a3b7e4b.js %}

We’ll then replace the Field component declaration here with the autocomplete component. To do that, locate where Field is declared in the JSX template.

_components/checkout/address-field.jsx_
{% gist https://gist.github.com/lobot/96772502476a19b051fdba6b7c065bfd.js %}

Replace that with the following:

_components/checkout/address-field.jsx_
{% gist https://gist.github.com/lobot/c8006f89915d9ded609ccc47a4b578fa.js %}


## Adding address field to form						

Let’s now add our newly created address field to the checkout form. The first thing we’ll do is import the component at the top of the file components/checkout/information-step.jsx.

_components/checkout/information-step.jsx_
{% gist https://gist.github.com/lobot/95eb0d2a742e27912fb57b24c3f69b3f.js %}

Next, in the same file, we’ll replace the address line 1 InputField component. You can identify it by the id address_1.
								_components/checkout/information-step.jsx_
{% gist https://gist.github.com/lobot/984d030a923a836b3d12e0a019d2af6c.js %}

Replace that with the following:

_components/checkout/information-step.jsx_
{% gist https://gist.github.com/lobot/c9f5c35aa6a27f80355ec2713ba438c7.js %}

Note that we keep the _id, error_, and _errorMsg_ props but not the others as they aren’t relevant in our new address field.


## Adding styling

To make the Lob autocomplete component fit with the Medusa checkout’s appearance we’ll need to add a few CSS rules.									

Let’s create a CSS module in the styles directory called address.module.css.

{% gist https://gist.github.com/lobot/975d6ca710ee5d821334e7846b6e30fb.js %}

Put the following rules into that new file:

 _styles/address.module.css_
{% gist https://gist.github.com/lobot/a00d5fd3922e027b3577d026bfc3250d.js %}

Let’s now import the CSS module file into our address field component and apply the class _`addressStyle.address`_ to the autocomplete component.

_components/checkout/address-field.jsx_ 
{% gist https://gist.github.com/lobot/6ef395b339a204069a48edf5ce84f086.js %}

With that done, the autocomplete component has now been integrated into the checkout. Go ahead and start typing into the form and you should see the address autocomplete working:

![example of address autocomplete working](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q1lz4kcgwafm7hu4jak5.png)


## Setting up state field								

As mentioned, the checkout form doesn’t include a field for the customer’s state by default. We’ll need this field as it’s required for US shipping addresses.								
Although not in the form, the Medusa checkout API does include a field “province” which we should use for the state.									

We’ll first create the field in the form’s validation schema which is handled by the library [Yup](https://github.com/jquense/yup). You’ll see the config object already has a value province that is set to be nullable. Let’s change this so it’s now required by removing nullable() and replacing it with `required("Required")`.

_components/checkout/information-step.jsx_
{% gist https://gist.github.com/lobot/cdf26cd0e09baa2bc48b68db28abddea.js %}

The checkout also uses the form library [Formik](https://formik.org/). This has a prop initialValues which allows the form to be pre-filled with saved values for returning customers.

Let’s add the province field to the _initialValues_ by adding a property _province_ and assigning to it `savedValues.province || "" `.	

_components/checkout/information-step.jsx_
{% gist https://gist.github.com/lobot/441ba459095b7370c14756870c11b702.js %}


### Adding state field to template									

We’ll now add the state (i.e., province) field to the form. We’ll make it share a row with the country field so the form is not too long.								

To do this, find the field with id _`country_code`_. Wrap this in a div with className _`styles.sharedrow`._									

Add an _`InputField`_ child with id _`province`_. You can make the placeholder “State” so it’s consistent with US addresses.

{% gist https://gist.github.com/lobot/5c4a27e4a32c5279f34f20caa9aa6fde.js %}

With that done, the form will now have a state field next to the country field.

![checkout form with state field](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mrpzv0xqz8reukjvgd9j.png)


## Creating select handler

Looking again at the address autocomplete field, you’ll see that as we begin typing an address we get suggestions in a drop-down below.
									
When the user selects one of these suggestions, the autocomplete component calls an _`onSelection`_ callback and passes the selected address to it.

Let’s create a handler function _`handleSelect`_ and pass it to the _`onSelection`_ prop. In this function, we’ll take the selected autocomplete address and populate the other address fields in the form.									

The first thing we need to do is import the _`useFormikContext`_ hook from the _`formik`_ module. This gives us access to the form API in a functional component.									
Let’s then destructure the object to get the _`setFieldValue`_ method. 

_components/checkout/address-field.jsx_
{% gist https://gist.github.com/lobot/c80b49d13c6790fd0626ee3348bf49bd.js %}

Now we can define the callback function. This function will receive an object argument that has a property. This is itself an object with the full address components as sub properties.

Let’s now use the _`setFieldValue`_ method in the callback to provide values for postal_code, city, province, address_1 and country_code.

{% gist https://gist.github.com/lobot/f3ef64046357bed9c8db35bb0088c8fd.js %}

Finally, we’ll assign handleSelect to the onSelection prop. We’ll also add the primaryLineOnly prop. What this does is ensure that when the user makes a selection that the entire address (with state, country, zip code, etc.) is not populated in the address field—just the primary line is e.g., “12 Test St”.

_components/checkout/address-field.jsx_
{% gist https://gist.github.com/lobot/ab56a4a3acb911764fc33049bd88175c.js %}


## Wrap up

With that done, we now have implemented a quick and stylish address autocomplete in Medusa! By typing a few characters into the autocomplete, customers get their validated address pre-filled, saving them a significant amount of time.

![final checkout form with all fields](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2pemcmx6jwc7jzv6mll5.png)