clubmate.fi

A good[ish] website

Web development blog, loads of UI and JavaScript topics

Filterable list with React

Filed under: UI components— Tagged with: React

This post looks into how to make a list which has a search field, so that the user filter the list.

Demo

This is what we’re building:

  • foo
  • bar
  • baz
  • quix

The React component

Here’s code for that example, I’ve added explanations below for the highlighted lines:

const listItems = ['foo', 'bar', 'baz', 'quix']

const FilterableList = () => {
  const [searchResults, setSearchResults] = useState(listItems)
  const handleChange = event => {
    const value = event.target.value.toLowerCase()

    if (value) {
      const filteredItems = listItems.filter(item =>        item.toLowerCase().includes(value)      )
      setSearchResults(
        filteredItems.length > 0 || value ? filteredItems : listItems      )
    } else {
      setSearchResults(listItems)    }
  }

  return (
    <Wrap>
      <Input onChange={handleChange} placeholder="Search" type="text" />
      <ul>
        {searchResults.length < 1 ? (
          <li>No results</li>        ) : (
          searchResults.map(item => <li key={item}>{item}</li>)        )}
      </ul>
    </Wrap>
  )
}
Line 4
Put your data into a state, we’ll need that later on.
Lines 10-12
This is the actual search, don’t lowercase them if you want the search to be case sensitive. Note: Remember to use the original data listItems, not the data in the state.
Line 15
Set the filtered results into the state.
Line 18
If the field is empty, fall back to the unfiltered list.
Line 27
Let the user know if there wasn’t any results.
Line 29
Render the list from the state, if the state changed React will rerender the component.

Sprinkle some accessibility on it

Hope you’re still reading, because this is important.

We need to tell screen readers to announce the changes that have happened on the page when filtering. This can be done by defining the list as an ARIA live region, see the highlighted lines and the explanation below:

ARIA stands for: Accessible Rich Internet Applications
<>
  <Input
    aria-controls="tag-list"    aria-label="search"    onChange={handleChange}
    placeholder="Search"
    type="text"
  />
  <ul aria-live="polite" id="tag-list" role="region">    {searchResults.length < 1 ? (
      <li>No results</li>
    ) : (
      searchResults.map(item => <li key={item}>{item}</li>)
    )}
  </ul>
</>
aria-controls="tag-list"
This attribute tells the screen reader that this field controls the list below with the id of tag-list.
aria-label="search"
We don’t have a label in the form field so we can lable it like this.
aria-live="polite"
This marks the element as a live region, meaning it might update dynamically. The value of the attribute defines how the changes to the `tag-list` are announced. Other values can be assertive or off.
role="region"
The region role is used to identify document areas the author deems significant. It is a generic landmark available to aid in navigation when none of the other landmark roles are appropriate. Read more about regions.

Conclusions

It’s just bliss to build stuff like this with React, it was made for this stuff. Also this is one of the cases where you need to keep accessibility in mind, because the basic HTML itself isn’t enough but you need to add some ARIA attributes.

Comments would go here, but the commenting system isn’t ready yet, sorry.

  • © 2022 Antti Hiljá
  • About
  • All rights reserved yadda yadda.
  • I can put just about anything here, no one reads the footer anyways.
  • I love u!