Using the State Hook to Search and Filter Data
Published: 2023-05-17 14:59:38

What is a Hook? A Hook is a special function that lets you “hook into” React features.  useState is a special hook that allows us to add React State to function components. 

Before React.js, in order to add state, one had to convert a function to class, but that's no longer necessary with the `useState` hook.

Let's begin by importing the hook to our React app. 


```

import { useState } from "react";
import React from "react";

```

Once we've imported the hook, we need to create our state variable and setter function:

 

```

const [searchText, setSearchText] = useState('')

```


`searchText` is our state variable.  It will hold the value of whatever the user types into the input box. 

`setSearchText` is our setter function.  By invoking it, we can change or update the state variable.

Finally, the value in the parenthesis attached to `useState` is our default state.  We would like the box to be empty, so we will simply pass an empty string as the parameter.

If, for any reason, you wanted the search box to already have text inside of it when the user loads the page, you can place something between these parenthesis. 


##setting state with `onChange`

Now that we have our setter function, we can use it to build out the function that will handle any change in the search input box. 

```

 const handleSearchInput = (event) => {
   setSearchText(even.target.value)


      <input type="text"  onChange={handleSearchInput} value={searchText} />

```


So we've created a function `handleSearchInput`, and added it to a react event listener, `onChange`, so that it will be invoked with every change to the input box. 

`handleSearchInput` simply uses our setter function, `setSearchText`, passing the `event.target.value` (the value of the text inside the search box) as a parameter.  This will update our `searchText` state.

Finally, we also place our _deconstructed_ searchText variable as the "value" attribute  of the `<input />` tag, ensuring that our value in the `searchText` variable and the value in the html remain constant.


## filtering the data using state

Now that we have our state synced, we need to do _something_ with this data.  Let's filter it, so that we will only show items with a title that matches the search query.  We can use the built in js _filter_ method. This method takes a callback function and returns an array that matches the search criterion. 


```

const filteredData = data.filter((d) => {
      return d.title.toLowerCase().includes(searchText.toLowerCase()) 


```

Here we name a new constant, that will return an array of data items with a title that matches the search query.  As our setter function is being invoked with each keypress, the user does not need to press enter.  This is a responsive search.

Yet, **what if there's nothing in the search box?**  If we want to display all of the available data, we can add an _if statement_ to our function.

```

const filteredData = data.filter((item) => {
    if (searchText === "") {
      return true;
    }
    return item.title.toLowerCase().includes(searchText.toLowerCase()) 

```


##filtering for multiple cases


Finally, what if we want to return items that match the title or another piece of data, such as an item's description?

  To handle this case, we can add a simple _OR statement_ 
( `||` )
to check for a match in either the item's title or description.


```



const filteredData = data.filter((item) => {
    if (searchText === "") {
      return true;
    }
    return item.title.toLowerCase().includes(searchText.toLowerCase()) 

||
         
items.description.toLowerCase().includes(searchText.toLowerCase())

```