FuseJS
Tags: javascript, webdev
Published: 2020-07-13 06:54:27

Fuse.js is a powerful fuzzy-search library that comes with many tools fresh out the box. Even though it is stated as being "powerful" it is lightweight and holds zero dependencies. Some cool use cases it can have are instead of setting up a backend server dedicated to just searching you can use this library to handle that. It can handle client-side fuzzy searching of small to moderately large data sets. Now I will say that using Fuse for something like building Googles searching would be a bit much but the library but I love using it for my apps since its a very quick setup time and hardly every makes the code your writing complex.

Let's Take a look at some of their example code.
```Javascript
// 1. List of items to search in
const books = [
  {
    title: "Old Man's War",
    author: {
      firstName: 'John',
      lastName: 'Scalzi'
    }
  },
  {
    title: 'The Lock Artist',
    author: {
      firstName: 'Steve',
      lastName: 'Hamilton'
    }
  }
]

// 2. Set up the Fuse instance
const fuse = new Fuse(books, {
  keys: ['title', 'author.firstName']
})

// 3. Now search!
fuse.search('jon')

// Output:
// [
//   {
//     item: {
//       title: "Old Man's War",
//       author: {
//         firstName: 'John',
//         lastName: 'Scalzi'
//       }
//     },
//     refIndex: 0
//   }
// ] 
```
What I love most about Fuse is that it uses very simple javascript to make the searching possible then their library handles a lot of stuff under the hood. Fuse is also fairly quick and simple to set up I'll take you through those steps next.

You can install Fuse as a dependency with npm or yarn using the following commands respectively.
```
$ npm install --save fuse.js
```
```
$ yarn add fuse.js
```
Then you can simply just add them to your file with an import if you are using es6 like such
```
import Fuse from 'fuse.js'
```
or in regular javascript with a require
```
const Fuse = require('fuse.js')
```
Once you've done that you can start using Fuse in your application. 

So the reason I was using the library was to get a more social media feel when looking up users in my application since it was about inviting people to a virtual house party. Here is me using it.
```Typescript
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import Fuse from 'fuse.js';

const Search = ({ partyId, setPartyUpdate, update }: any) => {
  const [input, setInput] = useState('');
  const [users, setUsers] = useState([]);
  const [matches, setMatches]: any = useState([]);

  const fuse = new Fuse(users, {
    keys: ['username', 'nameFirst', 'nameLast'],
  });

  const getAllUsers = () => {
    return axios
      .get('/user/all')
      .then((res) => setUsers(res.data))
      .catch((err) => console.error(err));
  };

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

  const handleMatches = () => {
    const results: any = fuse.search(input);
    setMatches(results);
  };
```
In my component, I grab a list of all the users in my database and set them in my state with useState. After setting up the states variables we set up our fuse instance passing in the array of user objects to search through and then the keys for fuse to check fuzzy searches for. From there I use handle matches to call fuse.search on the users' array and check for the input variable that was set in the state whenever a user attempts to search for a username. Then we call setMatches and set it to whatever results gives back.

Fuse also comes with the option to explore more detailed and refined fuzzy searches according to your liking. There's actually a lot of other methods that Fuse has included with their library.

setCollection
```javascript
const fruits = ['apple', 'orange']
const fuse = new Fuse(fruits)

fuse.setCollection(['banana', 'pear'])
```

add
```javascript
const fruits = ['apple', 'orange']
const fuse = new Fuse(fruits)

fuse.add('banana')

console.log(fruits.length)
// => 3
```

remove
```javascript
const fruits = ['apple', 'orange', 'banana', 'pear']
const fuse = new Fuse(fruits)

const results = fuse.remove((doc) => {
  return doc === 'banana' || doc === 'pear'
})

console.log(fruits.length)
// => 1

console.log(results)
// => ['banana', 'pear']
```

removeAt
```javascript
const fruits = ['apple', 'orange', 'banana', 'pear']
const fuse = new Fuse(fruits)

fuse.removeAt(1)

console.log(fruits)
// => ['apple', 'banana', 'pear']
```

getIndex
```javascript
const fruits = ['apple', 'orange', 'banana', 'pear']
const fuse = new Fuse(fruits)

console.log(fuse.getIndex().size())
// => 4
```

These are all built into Fuse and can be accessed anytime. I will be exploring their functionality a bit more soon and will update this to have the presentation of that link in this blog. Thanks for the read!