Step 6

We want to filter the notes based on a search (query) term which a client provides. We need to:

  1. Provide a UI component to enter the search query.
  2. Store the query in a variable.
  3. Filter the notes based on the query.

To store the query, we have several options. I made a design decision to keep the query as a state inside DisplayNotes.js. I did this to filter the notes right there before iteratively passing each note to the Note component.

So, let's update the DisplayNotes to a class component with state!

class DisplayNotes extends Component {
  constructor(props) {
    super(props);
    this.state = {
      query: "",
    };
  }

  updateQuery = (query) => {
    this.setState({ query });
  };

  includes = (note) => {
    const query = this.state.query.trim().toLowerCase();
    return (
      query === "" ||
      note.title.toLowerCase().includes(query) ||
      note.text.toLowerCase().includes(query)
    );
  };

  render() {
    const { notes, deleteNote, classes } = this.props;
    return (
      <>
        <Search query={this.state.query} updateQuery={this.updateQuery} />
        <List>
          {notes.filter(this.includes).map((note, index) => {
            return <Note note={note} key={index} deleteNote={deleteNote} />;
          })}
        </List>
        <Link to="/add">
          <Fab aria-label={"Add"} className={classes.fab}>
            <Add />
          </Fab>
        </Link>
      </>
    );
  }
}

export default withStyles(styles)(DisplayNotes);

Notice the utility method includes is passed to the array method filter. In addition, the query and updateQuery are passed the Search component.

Let's update the Search component to include a search bar. Instead of styling one, we will use the material-ui-search-bar library. So, stop the app and install it.

npm install material-ui-search-bar

Next, update the Search.js file as follows:

import SearchBar from "material-ui-search-bar";

function Search(props) {
  const { query, updateQuery } = props;
  return (
    <SearchBar 
      value={query} 
      onChange={(newValue) => updateQuery(newValue)} 
      onCancelSearch={() => updateQuery("")} 
    />
  );
}

export default Search;

Save all the changes and run the app. Make sure the search feature works as expected.