Article original : How to Add Search to a React App with Fuse.js

La recherche est un moyen puissant d'aider les personnes visitant votre site à trouver le contenu qui est le plus important pour elles. Mais souvent, il est vraiment difficile de déterminer les règles et la logique pour y parvenir. Dans cet article, nous verrons comment utiliser fuse.js pour ajouter une recherche à nos applications.

Qu'est-ce que fuse.js ?

Fuse.js est une bibliothèque JavaScript qui fournit des capacités de recherche floue pour les applications et les sites web. Elle est agréable et facile à utiliser dès la sortie de la boîte, mais inclut également des options de configuration qui vous permettent d'ajuster et de créer des solutions puissantes.

Pourquoi la recherche est-elle importante ?

Que vous soyez un créateur de contenu ou que vous essayiez de vendre un produit avec votre site web, il est important d'aider vos visiteurs à trouver ce qu'ils cherchent.

Si vous construisez un site web d'e-commerce, vous voulez que quelqu'un puisse facilement trouver vos figurines en vinyle de Bender plutôt que de devoir fouiller tout le catalogue d'abord.

Que allons-nous construire ?

Nous allons commencer par un exemple de base de Create React App. Il inclura des informations sur les personnages sous forme de données structurées pour l'une de mes émissions préférées, Futurama, qui sont simplement affichées dans une liste HTML.

Avec cette liste, nous allons utiliser fuse.js pour fournir des capacités de recherche côté client, ce qui nous permettra de démontrer la recherche du personnage que nous cherchons par son nom et d'autres détails.

Étape 0 : Initialisation de notre application

Pour commencer, nous allons avoir besoin de contenu avec lequel travailler. J'ai commencé par construire une liste de personnages de Futurama sous forme de données JSON structurées que j'ai mises dans une liste avec une nouvelle application Create React App.

Image Démo de recherche de personnages de Futurama

Vous remarquerez également que j'ai déjà ajouté une entrée pour notre recherche. Elle n'est pas encore fonctionnelle, mais nous l'utiliserons pour commencer.

Si vous souhaitez commencer au même point, j'ai créé une branche avec mon dépôt de démonstration que vous pouvez cloner localement pour suivre le projet avec moi !

git clone --single-branch --branch start git@github.com:colbyfayock/my-futurama-characters.git

Branche Git "start"

Ou suivez le commit.

Étape 1 : Installation de Fuse.js

La première chose que nous voulons faire est d'ajouter Fuse.js à notre application. Dans votre projet, exécutez :

yarn add fuse.js
# ou
npm install --save fuse.js

Cela enregistrera la dépendance dans notre projet afin que nous puissions l'utiliser dans notre projet.

Ensuite, nous voulons importer la dépendance dans notre application afin de pouvoir commencer à construire avec elle. En haut de votre fichier, dans notre cas src/App.js si vous suivez avec moi dans un nouveau projet Create React App, ajoutez :

import Fuse from 'fuse.js';

Si vous voulez tester si cela fonctionne, vous pouvez console.log(Fuse) et voir notre classe Fuse que nous utiliserons pour créer nos capacités de recherche.

Image Classe fuse.js importée

Et avec cela, nous sommes prêts à commencer !

Suivez le commit

Étape 2 : Création d'une nouvelle instance de recherche Fuse

Pour utiliser Fuse.js, nous voulons d'abord créer une nouvelle instance.

En haut de votre composant, ajoutez :

const fuse = new Fuse(characters, {
  keys: [
    'name',
    'company',
    'species'
  ]
});

Ce que cela fait :

  • Crée une nouvelle instance de Fuse
  • Passe notre tableau d'objets characters
  • Spécifie les 3 clés dans nos données que nous voulons rechercher

Ensuite, pour effectuer la recherche, nous pouvons ajouter :

const results = fuse.search('bender');

Et si nous affichons les résultats dans la console, nous pouvons voir :

Image Résultats de recherche de base avec fuse.js

Vous remarquerez que nous avons plus de résultats que notre ami Bender. Fuse.js fournit une "recherche floue" ce qui signifie qu'il essaie de vous aider au cas où vous ne seriez pas sûr de ce que vous cherchez ou si vous faites une faute de frappe dans votre requête.

Pour avoir une idée de comment cela fonctionne, ajoutons l'option includeScore à notre recherche :

const fuse = new Fuse(characters, {
  keys: [
    'name',
    'company',
    'species'
  ],
  includeScore: true
});

Maintenant, nous pouvons voir l'attribut score dans notre objet de résultats.

Image Résultats de recherche Fuse.js avec score

Vous remarquerez que notre premier résultat a un score très bas. Avec fuse.js, un score plus bas signifie qu'il est plus proche d'une correspondance exacte.

Un score de 0 indique une correspondance parfaite, tandis qu'un score de 1 indique une non-correspondance complète.

Cela signifie qu'il est extrêmement probable que le premier résultat soit ce que nous cherchons, mais il n'est pas confiant dans les autres.

Ainsi, avec nos résultats, nous voulons les connecter à notre interface utilisateur. Si vous remarquez que notre sortie de tableau est différente de ce que nous mappons pour la liste HTML, créons une nouvelle variable que nous pouvons changer :

const results = fuse.search('bender');
const characterResults = results.map(character => character.item);

Ce que cela fait est de créer un nouveau tableau en utilisant la méthode map qui n'inclura que la propriété item de chaque objet de tableau.

Ensuite, si nous remplaçons notre map characters à l'intérieur de notre liste par characterResults.map :

<ul className="characters">
  {characterResults.map(character => {
    const { name, company, species, thumb } = character;

Nous pouvons maintenant voir que notre page n'affiche que les résultats pour "bender" !

Image Démo avec résultats filtrés

Suivez le commit !

Étape 3 : Configuration de la recherche dynamique basée sur l'entrée utilisateur

Maintenant que nous avons une recherche codée en dur qui fonctionne, nous voulons que quelqu'un puisse utiliser l'entrée de recherche pour rechercher !

Pour y parvenir, nous allons utiliser le hook useState et écouter les changements du champ input, ce qui créera dynamiquement une recherche pour nos données.

Tout d'abord, importez le hook useState de React :

import React, { useState } from 'react';

Ensuite, utilisons ce hook pour créer une instance d'état :

const [query, updateQuery] = useState('');

Ici, nous créons un nouvel état de query que nous pouvons mettre à jour avec updateQuery qui par défaut est une chaîne vide ('').

Avec cela, disons à notre entrée de recherche d'utiliser cette valeur query comme sa valeur :

<input type="text" value={query} />

À ce stade, rien ne devrait être différent, car nous utilisons une requête vide.

Image Démo avec résultats filtrés - rien n'a changé

Maintenant, ajoutons un gestionnaire d'événements à notre entrée que nous pouvons utiliser pour mettre à jour notre état :

<input type="text" value={query} onChange={onSearch} />

Et nous voulons créer cette fonction pour pouvoir l'utiliser :

function onSearch({ currentTarget }) {
  updateQuery(currentTarget.value);
}

Cela mettra à jour notre query avec la valeur de l'entrée chaque fois qu'elle change.

Maintenant que notre query contiendra ce que nous voulons rechercher, nous pouvons mettre à jour notre instance de recherche :

const results = fuse.search(query);

Et maintenant, si vous rechargez la page, elle est vide ! ?

Image Démo sans résultats

C'est parce que par défaut, Fuse voit notre requête vide et ne la fait correspondre à rien. Si nous recherchons maintenant quelque chose comme slurms, nous pouvons voir notre recherche se mettre à jour dynamiquement avec des résultats !

Image Démo avec résultats pour "slurms"

Si nous voulions corriger cela afin que tous nos résultats s'affichent lorsqu'il n'y a pas de requête, nous pouvons le faire avec une instruction if ou dans mon exemple, un ternaire, qui affichera tous les personnages s'il n'y a pas de requête :

const characterResults = query ? results.map(character => character.item) : characters;

Image Démo avec tous les résultats

Et avec cela, nous avons notre recherche de base !

Image Démo avec résultats filtrés pour "zoidberg"

Suivez le commit !

Que puis-je faire ensuite ?

Ajuster votre recherche

Fuse.js vient avec de nombreuses options que vous pouvez utiliser pour ajuster votre recherche comme vous le souhaitez. Vous voulez seulement montrer des résultats fiables ? Utilisez l'option threshold ! Vous voulez des requêtes sensibles à la casse ? Utilisez l'option isCaseSensitive !

https://fusejs.io/api/options.html

Définir la requête par défaut avec les paramètres d'URL

Parfois, vous voulez que quelqu'un puisse lier à un ensemble particulier de résultats. Pour ce faire, nous pourrions vouloir ajouter un nouveau paramètre d'URL comme ?q=bender.

Pour que cela fonctionne, vous pouvez récupérer ce paramètre d'URL avec JavaScript et utiliser cette valeur pour définir notre état query.

Rejoignez la conversation !