NextJS Algolia Autocomplete Keyboard 'enter' Not Triggering Navigation

by ADMIN 71 views

Introduction

In this article, we will explore the issue of the Algolia autocomplete not working with the 'enter' key in a NextJS application. We will delve into the code and provide a solution to this problem.

Problem Statement

When using the Algolia autocomplete in a NextJS application, the 'enter' key does not trigger navigation. This is a problem because it makes the autocomplete less user-friendly. In this article, we will explore the code and provide a solution to this problem.

Code Review

Let's take a look at the code that is causing the problem.

import * as React from 'react';
import { ALGOLIA_APP_ID, ALGOLIA_SEARCH_API_KEY, buildIndexName } from '../../../utils/indexer/consts';
import algoliasearch from 'algoliasearch';
import { getAlgoliaResults } from '@algolia/autocomplete-js';
import '@algolia/autocomplete-theme-classic';
import BaseAutoComplete from './BaseAutoComplete';
import { useRouter } from 'next/router';

const searchClient = algoliasearch(ALGOLIA_APP_ID, ALGOLIA_SEARCH_API_KEY);

export default function AutoCompletePosts() {
    const router = useRouter();

    return (
        <BaseAutoComplete
            openOnFocus={true}
            placeholder="Search in posts..."
            getSources={({ query }) => [
                {
                    sourceId: 'posts',
                    getItems() {
                        return getAlgoliaResults({
                            searchClient,
                            queries: [
                                {
                                    indexName: buildIndexName(),
                                    query
                                }
                            ]
                        });
                    },
                    templates: {
                        item({ item, components }) {
                            return <ResultItem hit={item} components={components} />;
                        }
                    },
                    getItemUrl({ item }) {
                        return item.url; // Ensure this URL is correct
                    },
                    onSelect({ item }) {
                        router.push(item.url); // Ensures keyboard navigation works
                    },
                }
            ]}
        />
    );
}

export function ResultItem({ hit, components }) {
    return (
        <a href={hit.url} className="aa-ItemLink">
            <div className="aa-ItemContent">
                <div className="aa-ItemTitle">
                    <components.Highlight hit={hit} attribute="title" />
                </div>
            </div>
        </a>
    );
}

Analysis

The code above is using the Algolia autocomplete library to create an autocomplete input field. The onSelect function is called when an item is selected, and it uses the router.push function to navigate to the selected item's URL. However, the 'enter' key is not triggering the onSelect function.

Solution

To fix this issue, we need to add an event handler to the autocomplete input field to listen for the 'enter' key press. We can use the onKeyDown event to achieve this.

import * as React from 'react';
import { ALGOLIA_APP_ID, ALGOLIA_SEARCH_API_KEY, buildIndexName } from '../../../utils/indexer/consts';
import algoliasearch from 'algoliasearch';
import { getAlgoliaResults } from '@algolia/autocomplete-js';
import '@algolia/autocomplete-theme-classic';
import BaseAutoComplete from './BaseAutoComplete';
import { useRouter } from 'next/router';

const searchClient = algoliasearch(ALGOLIA_APP_ID, ALGOLIA_SEARCH_API_KEY);

export default function AutoCompletePosts() {
    const router = useRouter();

    const handleKeyDown = (event) => {
        if (event.key === 'Enter') {
            const selectedItem = event.target.value;
            router.push(selectedItem);
        }
    };

    return (
        <BaseAutoComplete
            openOnFocus={true}
            placeholder="Search in posts..."
            getSources={({ query }) => [
                {
                    sourceId: 'posts',
                    getItems() {
                        return getAlgoliaResults({
                            searchClient,
                            queries: [
                                {
                                    indexName: buildIndexName(),
                                    query
                                }
                            ]
                        });
                    },
                    templates: {
                        item({ item, components }) {
                            return <ResultItem hit={item} components={components} />;
                        }
                    },
                    getItemUrl({ item }) {
                        return item.url; // Ensure this URL is correct
                    },
                    onSelect({ item }) {
                        router.push(item.url); // Ensures keyboard navigation works
                    },
                }
            ]}
            onKeyDown={handleKeyDown}
        />
    );
}

export function ResultItem({ hit, components }) {
    return (
        <a href={hit.url} className="aa-ItemLink">
            <div className="aa-ItemContent">
                <div className="aa-ItemTitle">
                    <components.Highlight hit={hit} attribute="title" />
                </div>
            </div>
        </a>
    );
}

Conclusion

Q: What is the issue with the Algolia autocomplete not working with the 'enter' key in a NextJS application?

A: The issue is that the onSelect function is not being called when the 'enter' key is pressed, which prevents navigation to the selected item's URL.

Q: Why is the onSelect function not being called when the 'enter' key is pressed?

A: The onSelect function is not being called because the Algolia autocomplete library does not provide a built-in way to listen for the 'enter' key press. To fix this issue, we need to add an event handler to the autocomplete input field to listen for the 'enter' key press.

Q: How do I add an event handler to the autocomplete input field to listen for the 'enter' key press?

A: To add an event handler to the autocomplete input field, you can use the onKeyDown event. You can pass a function to the onKeyDown event that will be called when the 'enter' key is pressed.

Q: What code do I need to add to the autocomplete input field to listen for the 'enter' key press?

A: You will need to add the following code to the autocomplete input field:

const handleKeyDown = (event) => {
    if (event.key === 'Enter') {
        const selectedItem = event.target.value;
        router.push(selectedItem);
    }
};

return (
    <BaseAutoComplete
        openOnFocus={true}
        placeholder="Search in posts..."
        getSources={({ query }) => [
            {
                sourceId: 'posts',
                getItems() {
                    return getAlgoliaResults({
                        searchClient,
                        queries: [
                            {
                                indexName: buildIndexName(),
                                query
                            }
                        ]
                    });
                },
                templates: {
                    item({ item, components }) {
                        return <ResultItem hit={item} components={components} />;
                    }
                },
                getItemUrl({ item }) {
                    return item.url; // Ensure this URL is correct
                },
                onSelect({ item }) {
                    router.push(item.url); // Ensures keyboard navigation works
                },
            }
        ]}
        onKeyDown={handleKeyDown}
    />
);

Q: What is the purpose of the handleKeyDown function?

A: The handleKeyDown function is called when the 'enter' key is pressed. It gets the selected item's URL and navigates to it using the router.push function.

Q: Why do I need to use the router.push function to navigate to the selected item's URL?

A: You need to use the router.push function to navigate to the selected item's URL because the onSelect function is not being called when the 'enter' key is pressed. The router.push function is used to navigate to the selected item's URL when the 'enter' key is pressed.

Q: Can I use the onSelect function to navigate to the selected item's URL instead of using the router.push function?

A: Yes, you can use the onSelect function to navigate to the selected item's URL instead of using the router.push function. However, you will need to modify the onSelect function to navigate to the selected item's URL when the 'enter' key is pressed.

Q: How do I modify the onSelect function to navigate to the selected item's URL when the 'enter' key is pressed?

A: To modify the onSelect function to navigate to the selected item's URL when the 'enter' key is pressed, you will need to add a check to see if the 'enter' key was pressed. If the 'enter' key was pressed, you can navigate to the selected item's URL using the router.push function.

Q: What is the final code that I need to add to the autocomplete input field to listen for the 'enter' key press?

A: The final code that you need to add to the autocomplete input field to listen for the 'enter' key press is:

const handleKeyDown = (event) => {
    if (event.key === 'Enter') {
        const selectedItem = event.target.value;
        router.push(selectedItem);
    }
};

return (
    <BaseAutoComplete
        openOnFocus={true}
        placeholder="Search in posts..."
        getSources={({ query }) => [
            {
                sourceId: 'posts',
                getItems() {
                    return getAlgoliaResults({
                        searchClient,
                        queries: [
                            {
                                indexName: buildIndexName(),
                                query
                            }
                        ]
                    });
                },
                templates: {
                    item({ item, components }) {
                        return <ResultItem hit={item} components={components} />;
                    }
                },
                getItemUrl({ item }) {
                    return item.url; // Ensure this URL is correct
                },
                onSelect({ item }) {
                    if (event.key === 'Enter') {
                        router.push(item.url);
                    }
                },
            }
        ]}
        onKeyDown={handleKeyDown}
    />
);

Note that you will need to modify the onSelect function to navigate to the selected item's URL when the 'enter' key is pressed.