Filtering a List in React - part 12

 

React tutorial - Learn react filter and filter the list component | elpeeda.net


In this part, I'm going to implement UI filtering that enables us to filter the list by course. When we choose a language or course from the drop-down list, we'll listen for that event and send the value to the Lists component. And to do that, we'll employ state hooks and parent-child interaction. 

Filtering List Component

We have a list of arrays in the App component that contain language key-value pairs for each element. I want to loop through this list and return a new array depending on the values contained in these objects. 

import Lists from './component/Lists'
import { useState } from 'react'

const course = [
  {   
      id: 'u1',
      name: 'Sandmus',
      language: 'JavaScript',
      level: 'Beginner'
  },
  { 
      id: 'u2',
      name: 'Simba',
      language: 'HTML/CSS',
      level: 'Medium'
  },
  { 
      id: 'u3',
      name: 'Jenny',
      language: 'JavaScript',
      level: 'Advance'
  }
]

const App = () => {
const [users, setUsers]  = useState(course)

 return <Lists detail="{users}" />
}
export default App

The filter() method does pretty much what we want in our case. A filter() is a JavaScript function that generates new array items depending on a provided array, checks the condition, and returns true or false.

Add the ListsFilter component and the ListsFilter.css file to the newUser folder, and inside the ListsFilter component, add an anonymous function and, return select built-in element with the options we want to choose from.

import './ListsFilter.css'

const ListsFilter = () => {
  return (
    <section className="lists-filter">
      <div className="lists-filter--wrapper">
        <label>Course</label>
        <select>
          <option value='HTML/CSS'>HTML/CSS</option>
          <option value='JavaScript'>JavaScript</option>
          <option value='React'>React</option>
        </select>
      </div>
    </section>
  )
}

export default ListsFilter

ListsFilter.css

.lists-filter {
  color: #111;
  padding: 1rem;
}
.lists-filter--wrapper {
  display: flex;
  justify-content: end;
  align-items: center;
  margin: 1rem;
}
.lists-filter label {
  font-size: 1.5rem;
  font-weight: bold;
  margin-right: 1.75rem;
}
.lists-filter select {
  font-size: 1.2rem;
  padding: 1rem;
  border: 4px groove steelblue;
}

Now that we've successfully added a dropdown list to the UI, I'd like to filter these items when I select any specific languages, such as React or Javascript, and when I do so, the list should be filtered out and only show what I've selected from the dropdown.

Let's examine how we can accomplish this. We'll use the onChange event to track changes to the <select> element when a new option is selected from the drop-down list, and we'll pass the function dropdownChangeHandler as a value in curly braces to that event.

<select onChange={dropdownChangeHandler}>
 ...
 
</select>

The component must now declare the dropdownChangeHandler function, which takes an object as a parameter by default. We'll use its target property, which contains a value property, to find out which value was chosen from the drop-down list. Let's log the data into the console to see if everything is operating properly. You can read a dedicated article about working with event handlers.

const dropdownChangeHandler = (e) => {
  console.log(e.target.value)
}

Currently, we want to pass this value, which represents a selected value from the ListsFilter component to the Lists component. However, since the Lists component is the parent component and the ListsFilter component is the child component, we must pass data from the child component to the parent component.

To retrieve values from the ListsFilter component, let's create a function called filterCourseHandler in the Lists component and pass the arguments named selectedCourse inside of it. For the time being, we can use the console and pass the selectedCouse argument inside.

const filterCourseHandler = (selectedCourse) => {
  console.log(selectedCourse)
}

Furthermore, I want to call this function within the ListsFilter component. To do this, In Lists.js we will declare props similar to events, onDropdown on the ListsFilter JSX element, and pass the handler function as a value to newly declared props which allows us to pass a function from the Lists component to the ListsFilter component.

<ListsFilter onDropdown={filterCourseHandler} />

We will send the argument props in parentheses to the ListsFilter component method, and then we can assign the property using dot notation in the dropdownChangeHandler function, which accepts the argument e.target.value, which returns the value of the chosen element.

const dropdownChangeHandler = (e) => {
  props.onDropdown(e.target.value)
}


This function accepts input and sends it to the Lists component, which will then receive the value. When we choose a value from the drop-down list in the browser, it will now call the function anytime the value of the drop-down list changes.

I now want to update the UI whenever a new value is received from the dropdown and only display the components that are related to that value. We are aware that updating and re-rendering require that the UI register the new state.

Let's register a new state in the Lists component using the useState hook, which will return two arrays.  Use the const and destruct pattern, pass the first variable, filterCourse, second value is going to state updating function setFilterCourse, and pass the initial value, "javascript," which will be the default value.

const [filterCourse, setFilterCourse] = useState('JavaScript')

The setFilterCourse function will now be called inside the dropdownChangeHandler function to update the current state, which is the value of filterCourse, to the new value. That function receives the changed value as an input.

const filterCourseHandler = (selectedCourse) => {
  setFilterCourse(selectedCourse)
  console.log(selectedCourse)
}

Now, when a value is chosen, I want to return a specific set of items. Create the function selectedCourse, where we will use the filter() method on the array "detail," pass the parameter "user," and check to see if the object "user.language" matches the current variable filterCourse value.

const selectedCourse = detail.filter(user => {
  return user.language === filterCourse;
})

This function returns true if the language stored in the state matches the value we choose from the drop-down menu; else, it returns false. 

Now, in JSX of the List component, we'll map over filter items, transform the array, and dynamically render the list.

{selectedCourse.map((user) => 
    <List key={user.id}
      name={user.name} 
      language={user.language} 
      level={user.level} 
     />
)}

One thing you'll notice is that we're passing the initial value javascript, but it's set to HTML/CSS by default. To make this work, we need to pass the variable filterCourse to the child component.

<ListsFilter selected={filterCourse} onDropdown={filterCourseHandler} />

The value attribute should now be passed to the root <select> element inside the ListsFilter component, along with the JSX attribute selected using props enclosed in curly braces. This will set the default value as the component's initial value in javascript.

a React application, that only displays the items that have been selected


And that's how filtering in React works. The complete code is below.

import List from './List'
import ListsFilter from './newUser/ListsFilter'
import {useState} from 'react'

const Lists = ({detail}) => {
  const [filterCourse, setFilterCourse] = useState('JavaScript')

  const filterCourseHandler = (selectedCourse) => {
    setFilterCourse(selectedCourse)
    console.log(selectedCourse)
  }
  const selectedCourse = detail.filter(user => {
    return user.language === filterCourse;
  });

  return (
      <section>
        <ListsFilter selected={filterCourse} onDropdown={filterCourseHandler} />
        {selectedCourse.map((user) => 
          <List key={user.id}
            name={user.name} 
            language={user.language} 
            level={user.level} 
          />
        )}
      </section>
    )
}
export default Lists
Lists Component Function

import './ListsFilter.css'

const ListsFilter = (props) => {
  const dropdownChangeHandler = (e) => {
    props.onDropdown(e.target.value)
  }

  return (
    <section className="lists-filter">
      <div className="lists-filter--wrapper">
        <label>Course</label>
        <select value={props.selected} onChange={dropdownChangeHandler}>
          <option value='HTML/CSS'>HTML/CSS</option>
          <option value='JavaScript'>JavaScript</option>
          <option value='React'>React</option>
        </select>
      </div>
    </section>
  )
}

export default ListsFilter
ListsFilter Component Function

0 Comments:

Post a Comment