Table of Contents
In my previous article, I explained how to filter numbers and strings in React. In this article, we will see how to filter an array of objects.
Project setup
Create a react app using the following command:
1npx create-react-app react-filter-object-array
Add the following css to index.css
:
1body {2 display: flex;3 justify-content: center;4}5ul {6 list-style-type: none;7 padding: 0;8}9li {10 margin: 10px 0;11 border: 1px solid;12 padding: 10px;13}14.experience_filter {15 display: flex;16 gap: 6px;17 margin: 10px 0;18}19.experience_filter button {20 cursor: pointer;21 border: 1px solid;22 border-radius: 4px;23 padding: 4px;24 background-color: white;25}26.experience_filter button.selected {27 background-color: wheat;28}
Update the App.js
with the following code:
1import { useState } from "react"23const employees = [4 {5 id: 1,6 name: "Tobe",7 experience: 4,8 department: "Accounting",9 },10 {11 id: 2,12 name: "Jolee",13 experience: 13,14 department: "Services",15 },16 {17 id: 3,18 name: "Muhammad",19 experience: 14,20 department: "Training",21 },22 {23 id: 4,24 name: "Hubie",25 experience: 5,26 department: "Sales",27 },28 {29 id: 5,30 name: "Yoshiko",31 experience: 16,32 department: "Services",33 },34 {35 id: 6,36 name: "Beatrix",37 experience: 17,38 department: "Human Resources",39 },40 {41 id: 7,42 name: "Jacob",43 experience: 4,44 department: "Engineering",45 },46 {47 id: 8,48 name: "Koren",49 experience: 4,50 department: "Accounting",51 },52 {53 id: 9,54 name: "Marissa",55 experience: 20,56 department: "Support",57 },58 {59 id: 10,60 name: "Rufe",61 experience: 18,62 department: "Training",63 },64]6566function App() {67 const [filteredEmployees, setFilteredEmployees] = useState(employees)68 return (69 <div className="App">70 <ul>71 {filteredEmployees.map(employee => {72 const { name, experience, department, id } = employee73 return (74 <li key={id}>75 <div>76 Name: <strong>{name}</strong>77 </div>78 <div>Experience: {experience} year(s)</div>79 <div>Department: {department}</div>80 </li>81 )82 })}83 </ul>84 </div>85 )86}8788export default App
Here we have a list of 10 employees and we are looping through them and displaying each employee's information on a card.
Filtering based on department
You can filter the employees by department using the following function:
1const filterByDepartment = department => {2 setFilteredEmployees(3 employees.filter(employee => {4 return employee.department === department5 })6 )7}
Here we are using the array filter function,
and passing a callback to it. The callback will be called for each item in the employees array.
If the callback returns true for an employee, only that employee will be added to the array,
which will be returned by the filter function.
We are setting the returned array to the filteredEmployees
state.
Now, let's add a dropdown to list unique departments:
1import { useState } from "react"23const employees = [4 //...5]67function App() {8 const [filteredEmployees, setFilteredEmployees] = useState(employees)910 const filterByDepartment = department => {11 setFilteredEmployees(12 employees.filter(employee => employee.department === department)13 )14 }1516 // Using Set to filter unique values17 const departments = Array.from(18 new Set(employees.map(employee => employee.department))19 )2021 return (22 <div className="App">23 <select24 onChange={e => filterByDepartment(e.target.value)}25 value={department}26 >27 <option value="" disabled>28 Select department29 </option>3031 {departments.map(department => {32 return <option key={department}>{department}</option>33 })}34 </select>35 <ul>36 {filteredEmployees.map(employee => {37 const { name, experience, department, id } = employee38 return (39 <li key={id}>40 <div>41 Name: <strong>{name}</strong>42 </div>43 <div>Experience: {experience} year(s)</div>44 <div>Department: {department}</div>45 </li>46 )47 })}48 </ul>49 </div>50 )51}5253export default App
Now if you run the application, and select a department, you should see the employees only from that department.
Filtering multiple values
If you need to add another filter, you can store the filter in a different state and run an useEffect hook, whenever the filer changes.
1import { useEffect, useState } from "react"23const employees = [4 //..5]67function App() {8 const [filteredEmployees, setFilteredEmployees] = useState(employees)9 const [department, setDepartment] = useState("")10 const [experience, setExperience] = useState()1112 // Using Set to filter unique values13 const departments = Array.from(14 new Set(employees.map(employee => employee.department))15 )1617 useEffect(() => {18 setFilteredEmployees(19 employees.filter(employee => {20 return (21 (!department || department === employee.department) &&22 (!experience ||23 (experience === "LESS_THAN_10"24 ? employee.experience < 1025 : employee.experience >= 10))26 )27 })28 )29 }, [department, experience])3031 return (32 <div className="App">33 <select onChange={e => setDepartment(e.target.value)} value={department}>34 <option value="" disabled>35 Select department36 </option>3738 {departments.map(department => {39 return <option key={department}>{department}</option>40 })}41 </select>42 <div className="experience_filter">43 <button44 className={`${experience === "LESS_THAN_10" ? "selected" : ""}`}45 onClick={() => setExperience("LESS_THAN_10")}46 >47 Less than 10 years48 </button>49 <button50 className={`${experience === "10_PLUS" ? "selected" : ""}`}51 onClick={() => setExperience("10_PLUS")}52 >53 10+ years54 </button>55 </div>56 <ul>57 {filteredEmployees.map(employee => {58 const { name, experience, department, id } = employee59 return (60 <li key={id}>61 <div>62 Name: <strong>{name}</strong>63 </div>64 <div>Experience: {experience} year(s)</div>65 <div>Department: {department}</div>66 </li>67 )68 })}69 {filteredEmployees.length === 0 && (70 <div>No employees matching the filter</div>71 )}72 </ul>73 </div>74 )75}7677export default App
In the above code, we have added an additional filter based on experience. Each time the user changes a filter, we are saving the filter to its corresponding state. Also, we are running useEffect each time the filter changes.
Inside the useEffect, we are checking if the department filter and experience filter is applied.
We have a not check (!department
and !experience
), so that we can apply the filter only if that particular filter is selected.
Clearing all filters
Finally, let's add a clear filter button, to clear all the filters:
1import { useEffect, useState } from "react"23const employees = [4 //..5]67function App() {8 const [filteredEmployees, setFilteredEmployees] = useState(employees)9 const [department, setDepartment] = useState("")10 const [experience, setExperience] = useState()1112 // Using Set to filter unique values13 const departments = Array.from(14 new Set(employees.map(employee => employee.department))15 )1617 useEffect(() => {18 setFilteredEmployees(19 employees.filter(employee => {20 return (21 (!department || department === employee.department) &&22 (!experience ||23 (experience === "LESS_THAN_10"24 ? employee.experience < 1025 : employee.experience >= 10))26 )27 })28 )29 }, [department, experience])3031 const clearFilters = () => {32 setDepartment("")33 setExperience()34 }3536 return (37 <div className="App">38 <select onChange={e => setDepartment(e.target.value)} value={department}>39 <option value="" disabled>40 Select department41 </option>4243 {departments.map(department => {44 return <option key={department}>{department}</option>45 })}46 </select>47 <div className="experience_filter">48 <button49 className={`${experience === "LESS_THAN_10" ? "selected" : ""}`}50 onClick={() => setExperience("LESS_THAN_10")}51 >52 Less than 10 years53 </button>54 <button55 className={`${experience === "10_PLUS" ? "selected" : ""}`}56 onClick={() => setExperience("10_PLUS")}57 >58 10+ years59 </button>60 </div>61 <button onClick={clearFilters}>Clear All filters</button>62 <ul>63 {filteredEmployees.map(employee => {64 const { name, experience, department, id } = employee65 return (66 <li key={id}>67 <div>68 Name: <strong>{name}</strong>69 </div>70 <div>Experience: {experience} year(s)</div>71 <div>Department: {department}</div>72 </li>73 )74 })}75 {filteredEmployees.length === 0 && (76 <div>No employees matching the filter</div>77 )}78 </ul>79 </div>80 )81}8283export default App
Source code and demo
You can download the source code here and view a demo here.
Do follow me on twitter where I post developer insights more often!