In this tutorial, you will learn how to create a simple React search component.  The component will take a collection of data, passed in via props, allow a user to filter those results within a search bar and then the results will be dynamically updated and displayed back to the user.  

The main purpose of this exercise is to teach you how to manage a collection of data being passed down into your component, how to move that data from props to state and then how to manage that data throughout the life-cycle of that component.  If that sounds like something you want to learn, then read on!

The Overview

To quickly outline what we want to achieve:

1. We need two properties to manage our collections state.  The first to hold the original pull list of items. The second to display the filtered list.  

2. Some code to move the data passed in as props into state - componentWillMount()

3. Some HTML to do the filtering

4. An event handler to take the user input, filter the collection and modify the state, forcing React to re-render the component

The Code


Below is the code required for the main component:

import React from 'react';

export default class MyFilteringComponent extends React.Component {
    state = {
        initialItems: [],
        items: []
    }

    filterList = (event) => {
      let items = this.state.initialItems;
      items = items.filter((item) => {
        return item.toLowerCase().search(event.target.value.toLowerCase()) !== -1;
      });
      this.setState({items: items});
    }

    componentWillMount = () => {
      this.setState({
          initialItems: this.props.content,
          items: this.props.content
      })
    }

    render() {
      return (
        <div>
          <form>
                <input type="text" placeholder="Search" onChange={this.filterList}/>
          </form>
          <div>
            {
                this.state.items.map(function(item) {
                    return <div key={item}>{item}</div>
                })
            }
            </div>
        </div>
      );
    }
};

In the render() method there are two controls, the search box and some code that iterates through a collection.  The import part here is that we used state, rather than the prop being passed in.  One thing to note if you don't see anything being rendered when you are iterating through a collection using map() remember to include the return statement.  It's very easy - voice of experience - to just write the HTML and omit it.  When you render your application and scratch your head why nothing displays on the screen, you feel very foolish afterwards.

To store the collection into state, we add code within componentWillMount(), this will get called after the initial render of the component.  Anytime a new prop gets passed in, this will be run.  In here I set two properties.  One called 'initialItems' to store the original collection passed in.  This will be our source of truth for all the filtering we need to do.  The other one called 'items' will be used to store our filtered data.  This is the collection that we will render and the user will see on screen.

On the search box, we attach an event handler when the component updated called 'filterList'.  The code in here should be a little more familiar.  We get the full collection of data, use the text entered in the search box to filter the results.  We then save the newly created filtered data in the 'item' state.  When the items are saved in state, this will cause a re-render and react will update the UI.

To quickly complete the code, you would call the component like so:

import React, { Component } from 'react';
import MyFilteringComponent from './my-components/filter-component';

class App extends Component {
  render() {

    const countries =
    [
        "Afghanistan",
        "Åland Islands",
        "Albania",
        "Algeria"
    ];

    return (
        <MyFilteringComponent content={countries} />
    );
  }
}

export default App;

Things To Keep In Mind When Things Get More Complicated

Managing state and passing props around in a simple application is usually fairly easy to get your head around.  In large applications, where you have data being composed with a large hierarchy of nest high-order components, then things can become a little more complicated. The main thing to remember when filtering some data within a component is that you will need to use state, rather than just passing everything down as props.  If you have a big hierarchy, updating some props alone might not cause React to re-render your component so you can be left in a situation where the user types something but nothing updates on screen,

You can see a working example of this in my sample react app, available on github here.