0

I'm trying to build a searching feature in my app and It seems I'm super stuck at this one ...

Considerations:

const [rows, setItems] = useState([]); is where all objects is stored from the db.

const [search_data_suggestions, setSearchDataSuggestions] = useState([]); Should store whatever result from the search.

My text search field is represented by:

      <TextField 
      label="Search me"
      onChange={e => SearchView(e)}
      variant="outlined"
      InputProps={{
        startAdornment: (
          <InputAdornment position="start">
            <i className="fas fa-search"></i>
          </InputAdornment>
        )
      }}
      />
      </div> 

And my SearchView function does:

  const SearchView = (e) => {
    if (!e.target.value) {
      setSearchDataSuggestions([])
      setSearchField(null)

    } else {
      setSearchField(true)
      props.setSeachingView(true)
      for (const row of Object.values(rows)) {
        Object.keys(row).forEach(function (item, index) {
          if (typeof(row[item]) === 'string' && row[item].toLowerCase().includes(e.target.value.toLowerCase().trim())) {
            setSearchDataSuggestions([...search_data_suggestions, (rows[index])])

          }

        });
        }
    }   
  }

Can someone please point me to a direction on how to do that ?

All I want, is be able to search in a text field and update the data in another state (search_data_suggestions) so I can re-use this in a datatable.

Does it make sense?

Thank you.

3 Answers3

0

it sounds like you're trying to setState as you iterate over your array, is that right? if so that is a problem as setState is an Async operation for one and more importantly doing this will result in setting state over and over again.

React change state in array (for loop)

it's best you loop over your data and setState upon completion. Assuming that's your goal.

Farnoosh
  • 187
  • 1
  • 8
0

Your SearchView should do something like this

const SearchView = (e) => {
    if (!e.target.value) {
      setSearchDataSuggestions([])
      setSearchField(null)

    } else {
     let newSuggestions = []; 
      setSearchField(true)
      props.setSeachingView(true)
      for (const row of Object.values(rows)) {
        Object.keys(row).forEach(function (item, index) {
          if (typeof(row[item]) === 'string' && row[item].toLowerCase().includes(e.target.value.toLowerCase().trim())) {
            newSuggestions.push(rows[index]);
          }
        });
        }
      setSearchDataSuggestions(newSuggestions);
    }   
  }

You would do something like this for two reason, 1) setState is an asynchronous operation 2) Putting setState in the loop would cause it to set the state on each iteration, even if the previous value is set or not (since it is asynchronous)

Hope this helps!!

Rakesh Jain
  • 245
  • 1
  • 9
0

If you want to make a client-side search i suggest you to look at fuse.js which will add fuzzy search for free and your users will love it :) works great up to 1000 records. #LittleBigDetails

you could also add a debounce to improve performance

you can find a nice example using React here : https://codesandbox.io/s/5x24nmypxk

it use "old style" state but easily convertible to useState

jujule
  • 11,125
  • 3
  • 42
  • 63