DEV Community

Cover image for Simple search form in REACT using hooks 🔎.

Simple search form in REACT using hooks 🔎.

Asim Dahal on September 14, 2019

Searching is one of the most important components of your web application. Let's take an example of an E-commerce platform where there are thousand...
Collapse
 
clarity89 profile image
Alex K.

Nice tutorial :) One comment - you don't really need to set the filtered results on the state in this case. I'd just filter the people according to the search term during render:

function App() {
  const [searchTerm, setSearchTerm] = React.useState("");
  const handleChange = event => {
    setSearchTerm(event.target.value);
  };

  const results = !searchTerm
    ? people
    : people.filter(person =>
        person.toLowerCase().includes(searchTerm.toLocaleLowerCase())
      );

  return (
    <div className="App">
      <input
        type="text"
        placeholder="Search"
        value={searchTerm}
        onChange={handleChange}
      />
      <ul>
        {results.map(item => (
          <li>{item}</li>
        ))}
      </ul>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Here's a sandbox.

Collapse
 
aa_ziz profile image
Ahmed Aziz

Thank you, that was really helpful! One quastion: do you know how to make the search accept two seach parameters? like i want to search base on the name and also the address?

This what i tried, and failed :(

function App() {
  const [searchTerm, setSearchTerm] = React.useState("");
  const [searchTerm2, setSearchTerm2] = React.useState("");

  const handleChange = event => {
    setSearchTerm(event.target.value);
  };

  const handleChange2 = event => {
    setSearchTerm2(event.target.value);
  };

  const results = !searchTerm || !searchTerm2
    ? people
    : people.filter(person =>
        person.name.toLowerCase().includes(searchTerm.toLocaleLowerCase())
    ||  person.address.toLowerCase().includes(searchTerm2.toLocaleLowerCase())
      );

  return (
    <div className="App">
      <input
        type="text"
        placeholder="Search name"
        value={searchTerm}
        onChange={handleChange}
      />
      <input
        type="text"
        placeholder="Search address"
        value={searchTerm2}
        onChange={handleChange2}
      />
      <ul>
        {results.map(item => (
          <li>{item}</li>
        ))}
      </ul>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
clarity89 profile image
Alex K. • Edited

I think it'd be const results = !searchTerm && !searchTerm2 instead of || otherwise the filtering will be applied only of both search terms are present.

Thread Thread
 
aa_ziz profile image
Ahmed Aziz
  const results =
    searchTerm || searchTerm2
      ? !searchTerm2
        ? people.filter(person =>
            person.name.toLowerCase().includes(searchTerm.toLocaleLowerCase())
          )
        : people.filter(
            person =>
              person.address.toLowerCase() ===
              searchTerm2.toLocaleLowerCase()
          )
      : people;

Enter fullscreen mode Exit fullscreen mode

i came up with this solution and it works now but only if one of the conditions is true. I want to make the method filter the two conditions in the same time. So like i want to know all the people that their name is Alex and lives in New york

Thread Thread
 
clarity89 profile image
Alex K.

For your specific case you can do like this:

const results = searchTerm && searchTerm2 ?
  people.filter(person =>
    person.name.toLowerCase().includes(searchTerm.toLocaleLowerCase()) &&
    person.address.toLowerCase().includes(searchTerm2.toLocaleLowerCase())
  ) : people

However, note that the filter won't be applied unless both search terms are present.

Thread Thread
 
aa_ziz profile image
Ahmed Aziz

Yah but that is exactly what i don't want. I want that the user can choose one of the filters or both of them in the sametime

Collapse
 
abdullhrtima profile image
Abdullah Abu Rtima • Edited

call data from api and filter ....

import React ,{ useState  , useEffect} from 'react';
import axios from 'axios';

export default function Search() {
    const [data ,setData] = useState([]);
    const [filtered ,setFilterd] = useState([]);
    const [result , setResult] = useState("");

    useEffect(()=>{
            const fetchData = async ()=> {
                    try{
                        const res = await axios.get('https://jsonplaceholder.typicode.com/users');
                        setData(res.data);
                        setFilterd(res.data);
                    }catch(err){
                        throw new Error(err);
                    }
                     };
                  fetchData(); 
        },[]);

        useEffect(()=> {
            const results = filtered.filter(res=> res.name.toLowerCase().includes(result)

            ); 
            setData(results)
        } ,[result])
        //console.log(data)

      const onChange =(e)=> {
            setResult(e.target.value);
        }

    return (
        <div>
        <input 
            type="text"
            placeholder="serch here .."
            value={result}
            onChange={onChange}
        />
        {data.map((r,i)=> (   
                <ul key={i}>
                <li>{r.name}</li>
                </ul>)
            )
        }
    </div>
    )  
}

Enter fullscreen mode Exit fullscreen mode
Collapse
 
amitdotcode profile image
amit-dotcode

codesandbox.io/s/unruffled-bose-tk...

Please Help Me .. See my Code
The problem is when I search in the search field to my note app its work but when I remove search field text my old add data not show only search data show see my code you better understand that what I m trying to say

Collapse
 
moniqueboea profile image
moniqueboea

Thanks. I tried you exact code and get this warning:

29:6 warning React Hook useEffect has a missing dependency: 'filtered'. Either include it or remove the dependency array react-hooks/exhaustive-deps

Any suggestions?

My search isn't working

Collapse
 
moniqueboea profile image
moniqueboea

Actually, the search is working. I didn't realize that I had to type lower case. Can that be removed? Most people will start typing names in upper case (at least the first letter).

Collapse
 
rhadimer profile image
Rhadimer Antigua Sánchez

Excellent!

Collapse
 
riad_bx profile image
Riad

thanks a lot !! you made my day..

Collapse
 
sapien profile image
Prateek Thapa

Great.
One nitpick here: Make sure you trim your string for searching. Trim removes all the spaces at the start and end of the string.

people.filter(person => person.toLowerCase().includes(searchTerm.trim()));

Enter fullscreen mode Exit fullscreen mode
Collapse
 
adam_cyclones profile image
Adam Crockett 🌀

The cover photo looks like the macbook has tin worm 🐛

Collapse
 
asimdahall profile image
Asim Dahal

🤣🤣 Actually i got the picture from unsplash

Collapse
 
adam_cyclones profile image
Adam Crockett 🌀

Okay well whoever took it, they must have been worried about yin worm 😁

Collapse
 
geraldryan profile image
Gerald Ryan

This is great for simple arrays, but what about arrays of objects and you want the search to be broader in scope. For instance if you want to search a fitness class (which is an object) by name, or by duration, or by intensity or any other property

Collapse
 
belnako profile image
Belnako

How do I change the code if I want people to display as a list by default, without typing something in the searchbox?

Collapse
 
moniqueboea profile image
moniqueboea

Has anyone built a search app that has a form that the user submits and then display the results?

Collapse
 
butonix profile image
Butonix

Search only starts with a small letter. It doesn't work with the big one

Collapse
 
braxhawk profile image
Braxton Hawkins

Hi, thank you for this post, it was very helpful. I was wondering, is there a way to make the list hidden, and only show when the user is actually searching?

Collapse
 
kareemmarwan profile image
KareemMarwan

Thx bro

Collapse
 
amitdotcode profile image
amit-dotcode • Edited

when i try to use this code to filter i m facing this kind of error again and again please help

TypeError: oldData.toLowerCase is not a function

Collapse
 
bishwos profile image
Bishwo Shrestha

Great post

Collapse
 
mariapazmp profile image
Paz Muñoz

Hi!
What If I have in a separated component the Search Bar from the list of results? I want to know how can I send the results to a parent component :)

Collapse
 
rockinrone profile image
Ronny Ewanek

Thanks for this!

Collapse
 
fatemehqasemkhani profile image
fatemehqasemkhani

helpful, thanks.

Collapse
 
mohammadhani110 profile image
mohammadhani110

Love it ! Simple and easy to follow. Thanks alot

Collapse
 
wanderer3912 profile image
komal3912

Such a detailed post! helped a lot to understand hooks. Much appreciated.

Collapse
 
igorskiy profile image
Ihor Stavratii

It was realy helpful, thanks!
Maybe somebody know how to implement a feature which would highlight the searched results in the list?

Collapse
 
aytaa profile image
Aytaç Ünal

thanks bro