search
HomeWeb Front-endJS TutorialUsing MiniSearch in React: Advanced Search and Filtering Made Easy

Chapter One
What Is MiniSearch and How Does It Enhance JavaScript Filtering?

MiniSearch is a lightweight JavaScript library for full-text search within small to medium datasets. It indexes data and allows advanced search capabilities like fuzzy matching, prefix searches, ranking by relevance, and field weighting.

And by fuzzy matching, fuzzy matching means finding words or parts of words even if they are not typed exactly right. For instance, if you type "wlf" instead of "wolf", a fuzzy search will still find results that include "wolf".

And by prefix searches, prefix search looks for words or parts at the start of something. So, if you're searching for "car," a prefix search would also find "cart" or "carbonated."

These features given to us by miniSearch help us find what we are looking for even if it's not typed perfectly. Thus, making search results more accurate and helpful.

And Why do we Need it?

The first advantage it gives us is Advanced Search Features:
Traditional filtering usually matches exact values or basic patterns. MiniSearch provides more sophisticated text matching. These advanced search features can guess your mistakes, like if you type "bak" instead of "back", MiniSearch knows what you mean.

Another advantage it has over traditional filtering/ search is Relevance Ranking:
MiniSearch ranks results based on relevance, improving user experience in search-heavy applications. This ensures the most relevant results appear first. For instance, if you search for "JavaScript", the system prioritizes documents or items that mention "JavaScript" prominently or frequently, improving the overall search experience.

Now that we have that out of the way, let's create a basic React.js application and see how we use MiniSearch on the clientside.

Chapter Two
How to Set Up a React App with MiniSearch:

Ok, let's set up our project. And for us to set up the project, I will be using the ever-dependable vite. The text editor or IDE I will be using is the bad guy, Visual Studio code editor.

I will be setting up Vite with these prompts in the terminal. And I must say, I have already created these folders prior:

To go inside the visual_testing folder:

PS C:\Users\vawkei\Documents> cd .\visual_testing\

To go inside the building-in-public-slack folder:

PS C:\Users\vawkei\Documents\visual_testing> cd .\building-in-public-slack\

To go inside the minisearch folder:

PS C:\Users\vawkei\Documents\visual_testing\building-in-public-slack> cd .\minisearch\

To go inside the frontend folder:

PS C:\Users\vawkei\Documents\visual_testing\building-in-public-slack\minisearch> cd .\frontend\

Then in the frontend folder, I am going to install Vite, because that's where we want it to be, in our frontend folder.

I will install it with this line of code:

PS C:\Users\vawkei\Documents\visual_testing\building-in-public-slack\minisearch\frontend> npm create vite@latest .

Then it gives me options to choose from, I will be going with Javascript and React here. React as a framework and Javascript as a variant.

Once Done. I will be greeted by these:

PS C:\Users\vawkei\Documents> cd .\visual_testing\

Then I will install the minisearch package and the react-router-dom package. Though I won't be needing the react-router package in this tutorial:

PS C:\Users\vawkei\Documents\visual_testing> cd .\building-in-public-slack\

Will also install scss by running this code:

PS C:\Users\vawkei\Documents\visual_testing\building-in-public-slack> cd .\minisearch\

Now, this is not going to have a backend. Instead, I will place the data externally, somewhere. More on that later.

So if we now start our little app by running npm run dev in the terminal, we are gonna get a response like this in the terminal:

PS C:\Users\vawkei\Documents\visual_testing\building-in-public-slack\minisearch> cd .\frontend\

We will have to Follow the link (ctrl click) on this:

PS C:\Users\vawkei\Documents\visual_testing\building-in-public-slack\minisearch\frontend> npm create vite@latest .

If we ctrl click on:

Done. Now run:

 npm install
 npm run dev

We gonna be greeted by a page that looks like this in the browser:

Using MiniSearch in React: Advanced Search and Filtering Made Easy

Chapter Three
Cleaning the App.jsx":

The App.jsx would look like this initially:

PS C:\Users\vawkei\Documents\visual_testing\building-in-public-slack\minisearch\frontend> npm install minisearch react-router-dom

And this is what is responsible for the react logo and vite logo we saw in the picture above. However, we don't want to work with the present content of App.jsx, so we gotta clean it up. After cleaning it up, the content should look like this:

PS C:\Users\vawkei\Documents\visual_testing\building-in-public-slack\minisearch\frontend> npm install sass

This will leave us with a blank screen in our browser.

Chapter Four
Preparing the Project: Creating a Mock Database:

Normally, I should be getting data from a database, superbase, firebase, or whatever. Or even an API somewhere. I will be getting my data from a json file. I am gonna call it, db.json. The file will live in a folder called data, which should be at the root of our application. The content of the db file would look like this:

 VITE v5.4.11  ready in 332 ms

 ➜  Local:   http://localhost:5173/
 ➜  Network: use --host to expose
 ➜  press h + enter to show help

Yep! Your homeboy is a gamer.???. And just to let you know I am dying to play these titles.
Now, Let me just run through the file real quick.

The file contains a JSON object with an array of blog entries. Each object represents a video game and has the following fields:

title: The name of the video game.

text: A brief description of the game.

author: The person who wrote the blog entry.

id: A unique identifier for each blog post. e.g: "1","2","3"

Chapter Five
Setting Up a Mock Backend with JSON Server:

To get the database up and running, we will have to go to our terminal. We can open another port in the terminal, and run this command in the terminal:

http://localhost:5173/

The response we gonna get is this:

http://localhost:5173/

This means that our mock server/ database is ready for action.

Chapter Six
Building the Frontend: Creating the BlogList Component:

Alright! Now I am going to go inside the src folder and in there, create a component folder. Inside the component folder,  I will create another folder, call it blog. Inside the blog folder, I will create another folder called, blog-list. And inside this blog-list folder, I will create two files. BlogList.jsx and BlogList.module.scss. Won't be touching on the latter here.

Then set the BlogList component like this:

PS C:\Users\vawkei\Documents> cd .\visual_testing\

Chapter Seven
Routing in React: Rendering BlogList in App.jsx:

Now that we have built the basic structure of our BlogList, we have to get it connected to the App.jsx so it can be rendered on the screen/browser. To do that, let's dive into App.jsx file, and write out this code:

PS C:\Users\vawkei\Documents\visual_testing> cd .\building-in-public-slack\

Didn't touch on the Layout, since it's not useful here.

Then in the main.jsx, we will set up the Browser router there like this:

PS C:\Users\vawkei\Documents\visual_testing\building-in-public-slack> cd .\minisearch\

So with all these in place, whatever happens in our App.jsx would be visible in our browser/screen now.

Chapter Eight
Back to BlogList.jsx:
Setting Up the Blog and Loading States in BlogList.jsx

In here, I am going to create some states to work with and will also fetch the blog data from our local server which is running on localhost:8000.

The first state I will create is for blogs. It will start as an empty array when the App renders and will later get updated when we receive our blog data from the mock server.

Then the second state I will create, will be for loading. It will track whether the data is still being loaded. It starts as false and can be set to true while fetching data.

Soooooooooooooooo:

PS C:\Users\vawkei\Documents\visual_testing\building-in-public-slack\minisearch> cd .\frontend\

Chapter Nine
Displaying the data we fetched:
Building the Jsx:

First of all, I am going to build out the jsx component. And for that, I am going to write out this below in the return part:

PS C:\Users\vawkei\Documents\visual_testing\building-in-public-slack\minisearch\frontend> npm create vite@latest .

Chapter Ten
Displaying the data we fetched:
Here comes useEffect:

This doesn't do much. Even though we are getting the data in our console, it ain't showing up on the screen. And for it to show up on the screen, we will need the help of one of the bad guys of react, useEffect.

What is useEffect?
According to the NetNinja, "this hook, runs a function at every render of the component. Remember, the component renders initially when it first loads, and it also happens when a state changes. It re-renders the DOM, so it can update that state (the changed state) in the browser".

Soooooooooooooooo
The function we wrote earlier to fetchBlogs, we will put it in the useEffect:

PS C:\Users\vawkei\Documents> cd .\visual_testing\

Looking like the movie Inception? Just calm down, I will explain shortly. Not the movie Omen, But Oh! Men! this is the Christopher Nolan of Mern {M.E.R.N} right here.???

Then in the Jsx, we will code this there:

PS C:\Users\vawkei\Documents\visual_testing> cd .\building-in-public-slack\

Chapter Twelve
How it all looks like with MiniSearch:

Ok, now we can render the blogs on our screen. Let's now make use of MiniSearch. The whole code will look like this:

PS C:\Users\vawkei\Documents\visual_testing\building-in-public-slack> cd .\minisearch\

This code creates a new instance of MiniSearch to enable full-text search. Here's what it does:

fields: Specifies which fields (title, author, text) in the data will be indexed for searching.

storeFields: Defines which fields will be included in the search results. These fields are stored alongside the indexed data for easy retrieval.

Then this:

PS C:\Users\vawkei\Documents\visual_testing\building-in-public-slack\minisearch> cd .\frontend\

This code gives us the total number of documents that have been indexed by miniSearch after the page renders.

Now, let's go further. The page renders, and when it renders, the blog state is empty initially. We can see that courtesy of this in our code:

PS C:\Users\vawkei\Documents\visual_testing\building-in-public-slack\minisearch\frontend> npm create vite@latest .


 

After which, we get our data using the fetchBlogs function.There is data there for real, we know there's data by looking up this code:

Done. Now run:

 npm install
 npm run dev

Now this code:

PS C:\Users\vawkei\Documents\visual_testing\building-in-public-slack\minisearch\frontend> npm install minisearch react-router-dom

This is used to remove all previously indexed items. This is useful if you need to re-index new data or clear the current search index. We want to have a clean slate so we use it.

Then this:

PS C:\Users\vawkei\Documents\visual_testing\building-in-public-slack\minisearch\frontend> npm install sass

The miniSearch.addAll(data) method adds all the items in the data array to the MiniSearch index.

So after getting the data, we update blogs, by running this code:

 VITE v5.4.11  ready in 332 ms

 ➜  Local:   http://localhost:5173/
 ➜  Network: use --host to expose
 ➜  press h + enter to show help

Once we update the blogs state, The empty blogs array gets filled with our data.

In the process, we clean up our miniSearch instance to give room for fresh data to be indexed with this code:

http://localhost:5173/

And we add the received data to it by running this code:

http://localhost:5173/

With all these that took place, our miniSearch instance should be Loaded with data, yes it is. If you check out this line of code:

import { useState } from "react";
import reactLogo from "./assets/react.svg";
import viteLogo from "/vite.svg";
import "./App.css";

function App() {
  const [count, setCount] = useState(0);

  return (
    
           {" "}
      <div>
               {" "}
        <a href="https://vite.dev" target="_blank">
                    <img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/000/000/173282557470183.jpg?x-oss-process=image/resize,p_40" class="lazy" classname="logo" alt="Vite logo">     
           {" "}
        </a>
                <a href="https://react.dev" target="_blank">
                   {" "}
          <img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/000/000/173282557470183.jpg?x-oss-process=image/resize,p_40" class="lazy" classname="logo react" alt="React logo">     
           {" "}
        </a>     {" "}
      </div>
            <h1 id="Vite-React">Vite + React</h1>      <div classname="card">
               {" "}
        <button onclick="{()"> setCount((count) => count + 1)}>
          count is {count}       {" "}
        </button>
                <p>
          Edit <code>src/App.jsx</code> and save to test HMR        {" "}
        </p>     {" "}
      </div>      <p classname="read-the-docs">Click on the Vite and React logos to learn more       </p>
    >
  );
}
export default App;

It shows that there is data indexed there. However, upon re-rendering the page, we lose the data because miniSearch resets. We know this because of this code:

function App() {
  return      >;
}

export default App;

And look below, this is the actual content from our console.log upon running the code when it renders.

{
 "blogs": [
 {
 "title": "Wolfenstein",
 "text": "Wolfenstein is a groundbreaking video game series that pioneered the first-person shooter genre. Debuting in 1981, it gained fame with Wolfenstein 3D (1992), placing players in World War II as an Allied spy battling Nazis. Known for its intense gameplay, alternate history, and stealth-action elements, the series continues to evolve with modern reboots and thrilling narratives.",
 "author": "voke",
 "id": "1"
 },
 {
 "title": "Bioshock",
 "text": "BioShock is a critically acclaimed video game series blending first-person shooting with deep storytelling. Set in dystopian worlds like the underwater city of Rapture and floating Columbia, it explores themes of power, morality, and free will. Known for its immersive environments, philosophical depth, and plasmid abilities, BioShock redefined narrative-driven gaming since its debut in 2007.",
 "author": "ese",
 "id": "2"
 },
 {
 "id": "3550",
 "author": "jite",
 "title": "Doom",
 "text": "Doom is a legendary first-person shooter series that revolutionized gaming with its 1993 debut. Players battle demons from Hell across Mars and Earth, armed with iconic weapons like the shotgun and BFG. Known for its fast-paced action, heavy metal soundtrack, and gory visuals, Doom remains a cornerstone of the FPS genre and a cultural phenomenon."
 }
 ]
}

Chapter Fourteen
The Solution: Persisting MiniSearch Using useRef:

To prevent miniSearch from resetting on each render, we move it to a useRef so that the same instance persists across renders. Here's how:

PS C:\Users\vawkei\Documents> cd .\visual_testing\

This code block ensures that a single instance of MiniSearch persists across renders using useRef. miniSearchRef creates and stores the MiniSearch instance.

With this useRef code, we should be home and dry.

Explaining the handleSearch function:

PS C:\Users\vawkei\Documents\visual_testing> cd .\building-in-public-slack\

The handleSearch function takes in whatever the user types, it updates the state query with the user's input. (event.target.value). If the input is empty, it clears the results state and stops further processing. Then it uses miniSearch to search indexed data with fuzzy matching (allows slight mismatches). Then it updates the results' state.

Chapter Fifteen
Final Code:
So our final code in BlogList would look like this:

import { useEffect, useRef, useState } from "react";
import classes from "./BlogList.module.scss";
import MiniSearch from "minisearch";

const BlogList = () => {
  //create the blog and isLoading state.
  const [blogs, setBlogs] = useState([]);
  const [isLoading, setIsLoading] = useState(false);
  //create the query and results state.
  const [query, setQuery] = useState("");
  const [results, setResults] = useState([]);

  // checking if the blog state has been filled
  console.log(blogs);

  const miniSearchRef = useRef(
    new MiniSearch({
      fields: ["title", "author", "text"], // Fields to search on
      storeFields: ["title", "author", "text"], // Fields to return
    })
  );
  const miniSearch = miniSearchRef.current;
  console.log("Indexed Blogs after rendering:", miniSearch.documentCount);

  //fetching the blogs from our mock database:
  const fetchBlogs = async () => {
    setIsLoading(true);

    try {
      const response = await fetch("http://localhost:8000/blogs");

      if (!response.ok) {
        throw new Error();
      }

      const data = await response.json();
      console.log(data);

      miniSearch.removeAll();

      miniSearch.addAll(data);
      console.log("Indexed Blogs:", miniSearch.documentCount);

      setBlogs(data);
    } catch (error) {
      const message =
        error instanceof Error ? error.message : "Something went wrong";
      console.log(message);
    } finally {
      setIsLoading(false);
    }
  };

  // the search functionality:
  const handleSearch = (event) => {
    setQuery(event.target.value);

    if (event.target.value.trim() === "") {
      return setResults([]);
    }

    console.log(event.target.value);

    const searchResults = miniSearch.search(event.target.value, { fuzzy: 0.5 });
    console.log("searchResults:", searchResults);
    setResults(searchResults);
  };

  // Conditionally displaying or search results or blogs
  const displayPosts = results.length > 0 ? results : blogs;

  useEffect(() => {
    fetchBlogs();
  }, []);

  return (
    <div>
            <h2 id="BlogList">BlogList</h2>
      {isLoading && <p>Loading...</p>}     {" "}
      <div classname="{classes.search}">
               {" "}
        <input placeholder="search" value="{query}" onchange="{handleSearch}">     {" "}
      </div>
            <div classname="{classes.blogs}">
        {displayPosts.map((blog) => {
          // {blogs.map((blog) => {
          return (
            <div key="{blog.id}" classname="{classes.blog}">



<p><strong>Chapter Sixteen</strong><br>
<strong>Testing it out:</strong><br>
Now if I type wolfenst, this is what shows:</p>

<p><img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/000/000/173282557470183.jpg?x-oss-process=image/resize,p_40" class="lazy" alt="Using MiniSearch in React: Advanced Search and Filtering Made Easy"></p>

<p>You can see it didn't even wait for me to spell it completely before filtering it out.</p>

<p><em>Let's try out typing the critically:</em></p>

<p><img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/000/000/173282557528617.jpg?x-oss-process=image/resize,p_40" class="lazy" alt="Using MiniSearch in React: Advanced Search and Filtering Made Easy"><br>
Critically is not a name of a title, but it searches through our text and brings out every content that has the word critically in it. And it's safe to say that Bioshock is the only content that has critically in it.</p>

<p><strong>Final Thoughts</strong><br>
Thank you for sticking with me through this MiniSearch journey! I truly appreciate your time and patience, and I hope this guide has been helpful in navigating and understanding how to integrate MiniSearch effectively in your Reactjs project.</p>

<p><strong>About the Author</strong><br>
Voke Bernard is a passionate and driven M.E.R.N developer, that specializes in building dynamic React.js and Express.js applications. He is always looking to collaborate on new projects. Feel free to reach out if you are interested in working with him.</p>


          </div>

            
        </div>
</div>

The above is the detailed content of Using MiniSearch in React: Advanced Search and Filtering Made Easy. For more information, please follow other related articles on the PHP Chinese website!

Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Replace String Characters in JavaScriptReplace String Characters in JavaScriptMar 11, 2025 am 12:07 AM

Detailed explanation of JavaScript string replacement method and FAQ This article will explore two ways to replace string characters in JavaScript: internal JavaScript code and internal HTML for web pages. Replace string inside JavaScript code The most direct way is to use the replace() method: str = str.replace("find","replace"); This method replaces only the first match. To replace all matches, use a regular expression and add the global flag g: str = str.replace(/fi

jQuery Check if Date is ValidjQuery Check if Date is ValidMar 01, 2025 am 08:51 AM

Simple JavaScript functions are used to check if a date is valid. function isValidDate(s) { var bits = s.split('/'); var d = new Date(bits[2] '/' bits[1] '/' bits[0]); return !!(d && (d.getMonth() 1) == bits[1] && d.getDate() == Number(bits[0])); } //test var

jQuery get element padding/marginjQuery get element padding/marginMar 01, 2025 am 08:53 AM

This article discusses how to use jQuery to obtain and set the inner margin and margin values ​​of DOM elements, especially the specific locations of the outer margin and inner margins of the element. While it is possible to set the inner and outer margins of an element using CSS, getting accurate values ​​can be tricky. // set up $("div.header").css("margin","10px"); $("div.header").css("padding","10px"); You might think this code is

10 jQuery Accordions Tabs10 jQuery Accordions TabsMar 01, 2025 am 01:34 AM

This article explores ten exceptional jQuery tabs and accordions. The key difference between tabs and accordions lies in how their content panels are displayed and hidden. Let's delve into these ten examples. Related articles: 10 jQuery Tab Plugins

10 Worth Checking Out jQuery Plugins10 Worth Checking Out jQuery PluginsMar 01, 2025 am 01:29 AM

Discover ten exceptional jQuery plugins to elevate your website's dynamism and visual appeal! This curated collection offers diverse functionalities, from image animation to interactive galleries. Let's explore these powerful tools: Related Posts: 1

HTTP Debugging with Node and http-consoleHTTP Debugging with Node and http-consoleMar 01, 2025 am 01:37 AM

http-console is a Node module that gives you a command-line interface for executing HTTP commands. It’s great for debugging and seeing exactly what is going on with your HTTP requests, regardless of whether they’re made against a web server, web serv

Custom Google Search API Setup TutorialCustom Google Search API Setup TutorialMar 04, 2025 am 01:06 AM

This tutorial shows you how to integrate a custom Google Search API into your blog or website, offering a more refined search experience than standard WordPress theme search functions. It's surprisingly easy! You'll be able to restrict searches to y

jquery add scrollbar to divjquery add scrollbar to divMar 01, 2025 am 01:30 AM

The following jQuery code snippet can be used to add scrollbars when the div content exceeds the container element area. (No demonstration, please copy it directly to Firebug) //D = document //W = window //$ = jQuery var contentArea = $(this), wintop = contentArea.scrollTop(), docheight = $(D).height(), winheight = $(W).height(), divheight = $('#c

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
2 weeks agoBy尊渡假赌尊渡假赌尊渡假赌
Repo: How To Revive Teammates
4 weeks agoBy尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island Adventure: How To Get Giant Seeds
3 weeks agoBy尊渡假赌尊渡假赌尊渡假赌

Hot Tools

DVWA

DVWA

Damn Vulnerable Web App (DVWA) is a PHP/MySQL web application that is very vulnerable. Its main goals are to be an aid for security professionals to test their skills and tools in a legal environment, to help web developers better understand the process of securing web applications, and to help teachers/students teach/learn in a classroom environment Web application security. The goal of DVWA is to practice some of the most common web vulnerabilities through a simple and straightforward interface, with varying degrees of difficulty. Please note that this software

Atom editor mac version download

Atom editor mac version download

The most popular open source editor

Dreamweaver Mac version

Dreamweaver Mac version

Visual web development tools

PhpStorm Mac version

PhpStorm Mac version

The latest (2018.2.1) professional PHP integrated development tool

SecLists

SecLists

SecLists is the ultimate security tester's companion. It is a collection of various types of lists that are frequently used during security assessments, all in one place. SecLists helps make security testing more efficient and productive by conveniently providing all the lists a security tester might need. List types include usernames, passwords, URLs, fuzzing payloads, sensitive data patterns, web shells, and more. The tester can simply pull this repository onto a new test machine and he will have access to every type of list he needs.