Step 4

At this point, you should have something that looks like this:

Final product

Create SearchField component

Create a new component that will encapsulate the search field.

At this point, your App's render() function should somehow look like:

render () {
  return (
    <div>
      <Title>
        Product Page
      </Title>

      <SearchField />

      <ProductList products={products} />
    </div>
  );
}

Filter the list

Now that you have everyting on the screen, you want to listen to the onChange event on the <input> and filter the list accordingly.

As we have seen in the stateful components chapter, to be able to share information between components you will have to lift your state up to your App.js

The steps here are the following:

  • Create an initial state: To start, you will want to store an initial state in your App.js.

  export default class App extends Component {
    state = {
      productName: '',
    }
  }
  • Store user input: Create a handler function that you will pass to your SearchField that will update the state of your component

  handleUserInput = (event) => {
    const productName = event.target.value;

    this.setState({productName});
  }

  render() {
    return (
      ...
      <SearchField onChange={this.handleUserInput} />
      ...
    )
  }

✨ If you are not familiar with this synthax: yourFunction = (args) => {}, this will bind automatically this to be the function. Therefor, when you will pass the function to the component, yourFunction will keep the correct context.

Now, in your SearchField component, you will want to execute this onChange callback. So you want to listen to the onChange callback of the <input /> like:

  render() {
    const {onChange} = this.props;

    return (
      ...
      <input onChange={onChange} />
      ...
    )
  }

Note that on each key stroke, the onChange event will be fired. (Events are normalized by React. Feel free to learn more about React Synthetic events on their doc.) This means that on every keystroke, the state of App.js should be updated. To make sure everything is working properly, you can console.log(this.state.productName) in the render() function of App.js.

  • Filter the list:

Now that you store what the user entered you can filter the list on each render() and pass an filtered list to the ProductList component.

Here is a naïve filtering function that you can use:

// @items: Hash with key `title`
// @query: query with which the items will be filtered
function filterItems(items, query) {
  return items.filter(({title}) =>
    title.toLowerCase().includes(query.toLowerCase())
  );
}

Now in your render() function you can do something as easy as:

  render() {
    const {productName} = this.state;
    const filteredProducts = filterItems(products, productName);

    return (
      <div>
        ...
        <ProductList products={filteredProducts} />
        ...
      </div>
    );
  }

Last updated