Home > database >  render a list using map but filter base on user's query in frontend
render a list using map but filter base on user's query in frontend

Time:12-10

I want to achieve this result: https://resepi-khairulaming.vercel.app/

It's easy to just fetch the result from backend by passing the query, but how about doing the filter on the client side? do I need to hold 2 states, eg.

const [data, setData] = useState() // setData from api source on onl oad const [filteredData setFilteredData] = useState(data)

one is the original source and the another is the filtered source? Because the user can clear the query and I have to restore unfiltered data.

is there any better solution than this?

CodePudding user response:

You definitely need one state for the semi-persistent API results. For the filtered data to be rendered, having another state like you're thinking is a common option - there's nothing wrong with that.

Another option is to filter the API data before rendering, without an additional state.

return (
  <div>
    {
      data
        .filter(obj => obj.name.toLowerCase().includes(inputValue.toLowerCase())
        .map( /* etc */

Another is to memoize the filtered data, with a dependency array of the state from the API and whatever filters it.

const [data, setData] = useState([]);
const filteredData = useMemo(
  () => data.filter(obj => obj.name.toLowerCase().includes(inputValue.toLowerCase())
  [data, inputValue]
);

The inputValues and .names used above are just examples - replace with whatever your actual filtering mechanism is.

CodePudding user response:

Instead of setting and restoring the filtered state every time when a user tries to search for a value, memorization can be a possible and better option.

import React, {useState, useMemo} from 'react';

const Home = () => {
    const [data, setData] = useState([]);
    const [searchVal, setSearchVal] = useState('')

    const filteredData = useMemo(() => {
        return data.filter(dataItem => dataItem.name === searchVal);
    }, [data, searchVal])

    // use the filteredData in your list..
}

CodePudding user response:

So you want to optimize the search behaviour.

Here's what I noticed is happening, based on that example you sent and here are some optimization suggestions:

  1. The search is immediately triggered on the keydown or onchange event with no delay which may not be the ideal way of doing it. You want to either throttle or debounce in such a case. Look these terminologies up. They will save you multiple API calls. What they will help do is run the API query, only when the user stops typing for an X amount of time, otherwise don't.
  2. It's an API call to a database. In production, you may want to use ElasticSearch or a search engine which stores indexes in memory.
  3. You could also cache most searched results and first hit the cache, if missed, then query database. Options: Redis, Memcached, ElastiCache, ElasticSearch.
  4. Holding the data in a state is not a good option, unless the number of records is less. If it goes into thousands, you wouldn't want to make such an expensive call to your database and then hold that.

Other resources for you to read on: Full-Text Search (That's what this intended behaviour is called)

Suggestion for immediate fix: Make the database call after every onchange (if possible, try to implement debounce to save on API calls, it's easy)

  • Related