Autocomplete Component in Next.js with Mantine and TypeScript

When working on web applications, creating an intuitive and responsive user interface is paramount. One feature that significantly enhances user experience is an autocomplete input field. In this blog post, I will guide you through creating a zip code autocomplete component using Next.js 14, Mantine, and TypeScript. This component will dynamically fetch suggestions from an API as the user types, ensuring a seamless experience.

Thank me by sharing on Twitter 🙏

Introduction

Autocomplete inputs are incredibly useful for improving form usability. They help users quickly find and select from a list of suggestions, reducing the chance of errors and speeding up the input process. By integrating Mantine’s Autocomplete component with a custom Next.js API route, we can create a robust and efficient zip code autocomplete feature.

Setting Up the Next.js API Route

First, let’s create an API route in our Next.js 14 application to handle requests for zip codes. This API will simulate fetching data from a database or an external service.

Here’s the code for the API route:

TypeScript
// app/api/zipcodes/route.ts
import { NextRequest, NextResponse } from 'next/server';

export async function GET(request: NextRequest) {
  const { searchParams } = new URL(request.url);
  const query = searchParams.get('query') || '';

  // Simulate fetching data from a database or external API
  const zipcodes = ['12345', '23456', '34567', '45678', '56789'];
  const filteredZipcodes = zipcodes.filter((zipcode) =>
    zipcode.startsWith(query)
  );

  return NextResponse.json(filteredZipcodes);
}

This code defines a GET handler for the /api/zipcodes route. It retrieves the query parameter from the request URL, filters a predefined list of zip codes, and returns the filtered results as a JSON response.

Creating the Zip Code Autocomplete Component

Next, let’s create the ZipcodeAutocomplete component. This component will extend Mantine’s Autocomplete component and fetch zip code suggestions from our API as the user types. We will also ensure that the input is restricted to numerical values only.

Here’s the TypeScript code for the component:

TypeScript
// components/ZipcodeAutocomplete.tsx
'use client';

import { useState, useEffect } from 'react';
import { Autocomplete, AutocompleteProps } from '@mantine/core';
import { useDebouncedValue } from '@mantine/hooks';

// Extend the props of Autocomplete
type ZipcodeAutocompleteProps = Omit<AutocompleteProps, 'data'>;

export const ZipcodeAutocomplete: React.FC<ZipcodeAutocompleteProps> = (props) => {
  const [value, setValue] = useState<string>('');
  const [data, setData] = useState<string[]>([]);
  const [debouncedValue] = useDebouncedValue(value, 300);

  useEffect(() => {
    if (debouncedValue.trim().length === 0) {
      setData([]);
      return;
    }

    if (/^\d*$/.test(debouncedValue)) {
      fetch(`/api/zipcodes?query=${debouncedValue}`)
        .then((response) => response.json())
        .then((result: string[]) => setData(result));
    }
  }, [debouncedValue]);

  const handleChange = (val: string) => {
    if (/^\d*$/.test(val)) {
      setValue(val);
    }
  };

  return (
    <Autocomplete
      {...props}
      value={value}
      onChange={handleChange}
      data={data}
      label="Zipcode"
      placeholder="Enter zipcode"
    />
  );
};

In this component, I used the useDebouncedValue hook from Mantine to debounce the user input, preventing excessive API calls. The handleChange function ensures that only numerical values are accepted, using a regular expression to validate the input.

Using the ZipcodeAutocomplete Component

Now that we have our ZipcodeAutocomplete component, let’s integrate it into our main page. This will allow users to start typing a zip code and see autocomplete suggestions in real-time.

Here’s how you can include the component in a Next.js page:

TypeScript
// app/page.tsx
import { ZipcodeAutocomplete } from '../components/ZipcodeAutocomplete';

const Home: React.FC = () => {
  return (
    <div>
      <h1>Find Contractors</h1>
      <ZipcodeAutocomplete
        placeholder="Enter your zipcode"
        label="Zipcode"
        description="Type to search for zipcodes"
      />
    </div>
  );
};

export default Home;

This simple integration demonstrates how the ZipcodeAutocomplete component can be used in a real application. Users will see a labeled input field where they can start typing a zip code, and suggestions will appear dynamically based on their input.

Conclusion

Creating a zip code autocomplete component in a Next.js application using Mantine and TypeScript is straightforward and significantly enhances user experience. By leveraging Mantine’s Autocomplete component and integrating it with a custom API route, we can provide users with a responsive and efficient input field that dynamically fetches suggestions.

This approach not only improves usability but also ensures that the input is validated and restricted to numerical values, reducing the likelihood of errors. Whether you’re building a small project or a large application, adding features like autocomplete can make a big difference in how users interact with your forms.

I hope this guide helps you implement a similar feature in your projects. Happy coding!

Share this:

Leave a Reply