mug logo
    • Home
    • How-to guides
    • Snippets
    Cheatsheets:LinuxGitBckgrnd

React live search

September 20, 2021

post-bg

Content
Multiple cards components
Getting input value
Filtering out users

Starting point

Let's say I have a list of cards components each holding data about a user, and I want to add a search feature to it. Maybe something as shown here below:

cardlist131

Goal: live search update

I need a search box that takes the typed input and filters out the cards based on what a person types in.

I've initialized a cards's array. Cards's data is fetched during component mounting phase with the entire cards' list mapped out by CardList component.

app.js
------

 this.state = {
    cards: []
 }
 componentDidMount() {
    // fetch cards and
    // updates cards array
 }
...

render() {
  <div className="app">
    <CardList users={this.state.cards}>
  </div>
}

In order to live update my cards with the input generated from the search box, I need to store in whatever a person enters into the input box. So for that I create a new piece of state: searchField.

I also need to wire up an onChange event listener to react to changes, as new values are being entered.

Getting the input value

 this.state = {
    cards: []
    searchField: '',
 }
...

render() {
  return (
    <div className="app">
      <input
        type="search"
        placeholder="enter name"
        onChange={(e) => this.setState({
            searchField: e.target.value
        })}
    />

  <CardList users={this.state.users}>
  </div>
)}

Normally with React, if you console.log what's being entered into the input box, you'll noticed that the state although it gets updated, it's always a letter behind, but it's not a bug. It's because of React's state being asynchronous.

<input
  type="search"
  placeholder="enter name"
    onChange={(e) =>
      console.log(e.target.value)
    )}
/>

To log the actual value being entered into the search field, you need to pass the console.log var as the second argument to the setState function; which returns a callback with the updated state, as shown below.

<input
  type="search"
  placeholder="enter name"
  onChange={(e) => this.setState({
      searchField: e.target.value
  }, () => {
      console.log(this.state)
  })
/>

Filtering out users

Let's say the search field takes in peoples names, that are then run against our list of cards, in order to filter out those that don't match. So far it seems nothing more than a map/filter combination at most. What makes it a live search feature is the placement of the filtering function, within the render section of the component because it'll ensured that it gets updated everytime there's a state change.

Also we'd want to avoid modifying the actual cards array state as we do this.

render() {
  const { users, searchField } = this.state;
  const filteredUsers = users.filter(usr =>
    usr.name.toLowerCase().includes(
        searchField.toLowerCase()
    ))

  return (
    <div className="app">
      <input
          type="search"
          placeholder="enter name"
          onChange={(e) => this.setState({
              searchField: e.target.value
          })}
      />
      //no longer this.state.users
      <CardList users={filteredUsers}>
    </div>
)}

By using filteredUsers function, we're making sure not to modify the original card's array.

As a user types in, it triggers setState; which in turn sets the state value of searchField; which in turn causes the app to re-render, and recall the render method; which calls filteredUsers function returning a new array of re-filtered users, that are passed for re-rendering to CardList component; which in turn updates the current list of users shown in the page.

  • Terms & Conditions
  • kcosa.com © 2025
  • Privacy Policy