Step 6
We want to filter the notes based on a search (query) term which a client provides. We need to:
- Provide a UI component to enter the search query.
- Store the query in a variable.
- 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.