When setting up client search, we usually rely on string comparison methods like indexOf, contains, etc. These methods work fine, but in real-life situations, users may search using incorrect spellings, jumbled sentences, and so on. Fuzzy Search helps us solve these issues.
Fuzzy Search
Fuzzy Search, also known as Approximate String Matching, is a technique for finding strings that are similar but not exactly the same.
Now, let’s get started with building the application.
We’ll set up a basic page that includes text and a search box.
Basic React App for Search Demo
A simple React application to demonstrate the search functionality.
Regular Search
Typically, we use string comparison methods like indexOf, contains, etc. These work well, but they fail to provide results if the search query contains spelling mistakes.
Item.js
Displays individual items with their logo, name, and tags.
import React from "react"; const Item = (props) => { return ( <div className="item"> <div className="logo"> <img src={props.logo} alt={props.name} /> </div> <div className="name"> <p>{props.name}</p> <div className="tags">{props.tags.join(", ")}</div> </div> </div> ); }; export default Item;
Data.js
Contains various objects representing different technologies with their names, logos, and tags.
[ { "name": "Booty Bounce", "logo": "https://cdn.worldvectorlogo.com/logos/bootstrap-4.svg", "tags": ["dancing-css", "boot-stomping", "html-hop", "sass-swing"] }, { "name": "React-o-Rama", "logo": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a7/React-icon.svg/1280px-React-icon.svg.png", "tags": ["spinny-js", "state-masters", "fronty-mcfrontend"] }, { "name": "Angu-latte", "logo": "https://angular.io/assets/images/logos/angular/angular.png", "tags": ["typescript-tornado", "web-zest", "framework-feels"] }, { "name": "Vue-tiful Bliss", "logo": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/95/Vue.js_Logo_2.svg/1200px-Vue.js_Logo_2.svg.png", "tags": ["zen-js", "pretty-view", "framework-bae"] }, { "name": "Ant Party", "logo": "https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg", "tags": ["system-sass", "fancy-ui", "antd-vibes"] }, { "name": "Git Giggle", "logo": "https://git-scm.com/images/logos/downloads/Git-Icon-1788C.png", "tags": ["commit-fun", "repo-riff", "c-git-jig"] }, { "name": "Gruntastic", "logo": "https://gruntjs.com/img/og.png", "tags": ["js-run-wild", "task-mania"] }, { "name": "jQuirky", "logo": "https://w7.pngwing.com/pngs/265/442/png-transparent-jquery-octos-global-javascript-library-document-object-model-ajax-framework-text-trademark-logo-thumbnail.png", "tags": ["selecto-magic", "fun-dome", "libra-party"] }, { "name": "D3-Licious", "logo": "https://raw.githubusercontent.com/d3/d3-logo/master/d3.png", "tags": ["data-candy", "viz-buzz", "chart-bliss"] } ]
Setting.js
The code implements a search feature in a React app where users can search tools and technologies by name or tags. It filters the data in real time, making the search case-insensitive, and updates the displayed results as the user types in the search box.
import React, { useState } from "react"; import data from "./data.json"; import Item from "./item"; const SettingsPage = () => { const [searchData, setSearchData] = useState(data); const searchItem = (query) => { if (!query) { setSearchData(data); return; } query = query.toLowerCase(); const finalResult = []; data.forEach((item) => { if ( item.name.toLowerCase().indexOf(query) !== -1 || item.tags.includes(query) ) { finalResult.push(item); } }); setSearchData(finalResult); }; return ( <div> <p className="title">Tools & Technologies</p> <div className="search-container"> <input type="search" onChange={(e) => searchItem(e.target.value)} placeholder="Search Technologies" /> </div> <div className="item-container"> {searchData.map((item) => ( <Item {...item} key={item.name} /> ))} </div> </div> ); }; export default SettingsPage;
Output
Searched bot
Searched booty
I tried searching for “booty” and “bot,” but it only showed results for “booty” because the string comparison method works that way. We need a different string comparison algorithm to make the search fuzzy.
Many algorithms are available for this; you don’t need to study them all to use one.
To turn our search into a fuzzy search engine, we will use Fuse.js.
Fuse.js is a quick and lightweight fuzzy search library that doesn’t require any dependencies.
Integrating Fuse.js with Search
We can easily turn our search into a fuzzy one by making a small change.
setting.js
Implements the fuzzy search functionality using Fuse.js. It allows users to search through the technologies by their name and tags. The search results are refreshed instantly as the user types.
import React, { useState } from "react"; import data from "./data.json"; import Fuse from "fuse.js"; import Item from "./item"; const SettingsPage = () => { const [searchData, setSearchData] = useState(data); const searchItem = (query) => { if (!query) { setSearchData(data); return; } const fuse = new Fuse(data, { keys: ["name", "tags"] }); const result = fuse.search(query); const finalResult = []; if (result.length) { result.forEach((item) => { finalResult.push(item.item); }); setSearchData(finalResult); } else { setSearchData([]); } }; return ( <div> <p className="title">Tools & Technologies</p> <div className="search-container"> <input type="search" onChange={(e) => searchItem(e.target.value)} placeholder="Search Technologies" /> </div> <div className="item-container"> {searchData.map((item) => ( <Item {...item} key={item.name} /> ))} </div> </div> ); }; export default SettingsPage;
Output
Searched bot
Searched booty
Conclusion
This blog explored how traditional string comparison methods fall short in handling misspellings and inaccuracies in search queries. Fuzzy Search, implemented using Fuse.js, provides an efficient solution by enabling approximate string matching, making the search experience more robust and user-friendly. By integrating Fuse.js into a simple React application, we created a real-time case-insensitive, flexible search functionality that can deliver accurate results even for imperfect queries. This lightweight library is a game-changer for enhancing search features in modern applications.
Thank you for sharing good information.