Search code examples
reactjssearchreact-hooksfetch

Live searching of external data based on any character - React Hooks


I have input field, which when you click, the list of fetched data shows up. Now I need to be able to search through the data based on any letter the data includes.

Example: I have list of different colors - when I type in input field letter L - all colors that has this letter gets filtered across - bLack, yeLLow, bLue, etc....

const colorInformations = "secretURL";

const [colorData, setColorData] = useState([]);
    useEffect(() => {
        getColorInfo();
    }, []);
    const getColorInfo = async () => {
      try {
        const response = await fetch(colorInformations);
        const jsonData = await response.json();
        const { array1, array2 } = jsonData;
        const combinedData = array1.map(({ data1 }, i) => ({
          ...data1,
          ...array2[i].data2
        }));
        setColorData(combinedData); 
      } catch (err) {
        console.log(err)
      }
   };

Fetched Data:

 { colorData && colorData.map(( data1, data2,  index)  =>
        <li key={"index" + index}>
                    <div className="col-6 text ">
                      <h5>{data1.name} </h5>
                      <p>{data2.color} </p>  
        </li>
         )}   

For input I am trying to do this:

<input type="text" onChange={handleSearchChange} value={search} /> 

And handleSearchChange function:

const [search, setSearch] = useState("");

  const handleSearchChange = (e) => {
    setSearch(e.target.value)
 }

Here I got stuck, what I need to finish is:

  1. Filter the data based on letters - when L is typed all colors with L in are filtered

  2. When I click on specific color it needs to be shown in input form and it has to be remembered in list - so when list is opened again the clicked color is still active

I know I should use .filter() function - I am just not sure how and where


Solution

  • 1- add a new state for filteredData.

    const [filteredColorData, setFilteredColorData] = useState([]);
    

    2- onMount set the fetched data to the filtered data along with the actual data source.

    const getColorInfo = async () => {
        try {
          const response = await fetch(colorInformations);
          const jsonData = await response.json();
          const { array1, array2 } = jsonData;
          const combinedData = array1.map(({ data1 }, i) => ({
            ...data1,
            ...array2[i].data2
          }));
           setColorData(combinedData);
           setFilteredColorData(combinedData); // set fetched Data.
         } catch (err) {
          console.log(err);
         }
     };
    

    3- render the filtered data rather than the actual data.

     { 
        filteredColorData && filteredColorData.map(( data1, data2,  index)  =>
          <li key={"index" + index}>
            <div className="col-6 text ">
              <h5>{data1.name} </h5>
              <p>{data2.suggestion} </p>  
            </div>
          </li>
        ) 
      }
    

    4- implement the filter functionality which filters the data and set the filtered data, and rerender it to every user input.

    useEffect(() => {
        filterdata();
      }, [search])
    
      const filterdata = () => {  
        const filtered = colorData && colorData.filter((data1) => {
          return data1.name.toLowerCase().startsWith(search.toLowerCase())
        })
    
        setFilteredColorData(filtered);
      }
    

    also check this link for inspiration live working demo