Skip to content
react

How to filter an Array of Objects in React?

Aug 21, 2022Abhishek EH6 Min Read
How to filter an Array of Objects in React?

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:

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:

App.js
1import { useState } from "react"
2
3const 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]
65
66function 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 } = employee
73 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}
87
88export 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.

list of employees

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 === department
5 })
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:

App.js
1import { useState } from "react"
2
3const employees = [
4 //...
5]
6
7function App() {
8 const [filteredEmployees, setFilteredEmployees] = useState(employees)
9
10 const filterByDepartment = department => {
11 setFilteredEmployees(
12 employees.filter(employee => employee.department === department)
13 )
14 }
15
16 // Using Set to filter unique values
17 const departments = Array.from(
18 new Set(employees.map(employee => employee.department))
19 )
20
21 return (
22 <div className="App">
23 <select onChange={e => filterByDepartment(e.target.value)}>
24 <option value="" disabled default selected>
25 Select department
26 </option>
27
28 {departments.map(department => {
29 return <option key={department}>{department}</option>
30 })}
31 </select>
32 <ul>
33 {filteredEmployees.map(employee => {
34 const { name, experience, department, id } = employee
35 return (
36 <li key={id}>
37 <div>
38 Name: <strong>{name}</strong>
39 </div>
40 <div>Experience: {experience} year(s)</div>
41 <div>Department: {department}</div>
42 </li>
43 )
44 })}
45 </ul>
46 </div>
47 )
48}
49
50export 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.

App.js
1import { useEffect, useState } from "react"
2
3const employees = [
4 //..
5]
6
7function App() {
8 const [filteredEmployees, setFilteredEmployees] = useState(employees)
9 const [department, setDepartment] = useState()
10 const [experience, setExperience] = useState()
11
12 // Using Set to filter unique values
13 const departments = Array.from(
14 new Set(employees.map(employee => employee.department))
15 )
16
17 useEffect(() => {
18 setFilteredEmployees(
19 employees.filter(employee => {
20 return (
21 (!department || department === employee.department) &&
22 (!experience ||
23 (experience === "LESS_THAN_10"
24 ? employee.experience < 10
25 : employee.experience >= 10))
26 )
27 })
28 )
29 }, [department, experience])
30
31 return (
32 <div className="App">
33 <select onChange={e => setDepartment(e.target.value)}>
34 <option value="" disabled default selected>
35 Select department
36 </option>
37
38 {departments.map(department => {
39 return <option key={department}>{department}</option>
40 })}
41 </select>
42 <div className="experience_filter">
43 <button
44 className={`${experience === "LESS_THAN_10" ? "selected" : ""}`}
45 onClick={() => setExperience("LESS_THAN_10")}
46 >
47 Less than 10 years
48 </button>
49 <button
50 className={`${experience === "10_PLUS" ? "selected" : ""}`}
51 onClick={() => setExperience("10_PLUS")}
52 >
53 10+ years
54 </button>
55 </div>
56 <ul>
57 {filteredEmployees.map(employee => {
58 const { name, experience, department, id } = employee
59 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}
76
77export 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:

App.js
1import { useEffect, useState } from "react"
2
3const employees = [
4 //..
5]
6
7function App() {
8 const [filteredEmployees, setFilteredEmployees] = useState(employees)
9 const [department, setDepartment] = useState()
10 const [experience, setExperience] = useState()
11
12 // Using Set to filter unique values
13 const departments = Array.from(
14 new Set(employees.map(employee => employee.department))
15 )
16
17 useEffect(() => {
18 setFilteredEmployees(
19 employees.filter(employee => {
20 return (
21 (!department || department === employee.department) &&
22 (!experience ||
23 (experience === "LESS_THAN_10"
24 ? employee.experience < 10
25 : employee.experience >= 10))
26 )
27 })
28 )
29 }, [department, experience])
30
31 const clearFilters = () => {
32 setDepartment()
33 setExperience()
34 }
35
36 return (
37 <div className="App">
38 <select onChange={e => setDepartment(e.target.value)}>
39 <option value="" disabled default selected>
40 Select department
41 </option>
42
43 {departments.map(department => {
44 return <option key={department}>{department}</option>
45 })}
46 </select>
47 <div className="experience_filter">
48 <button
49 className={`${experience === "LESS_THAN_10" ? "selected" : ""}`}
50 onClick={() => setExperience("LESS_THAN_10")}
51 >
52 Less than 10 years
53 </button>
54 <button
55 className={`${experience === "10_PLUS" ? "selected" : ""}`}
56 onClick={() => setExperience("10_PLUS")}
57 >
58 10+ years
59 </button>
60 </div>
61 <button onClick={clearFilters}>Clear All filters</button>
62 <ul>
63 {filteredEmployees.map(employee => {
64 const { name, experience, department, id } = employee
65 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}
82
83export default App

Source code and demo

You can download the source code here and view a demo here.

If you have liked article, stay in touch with me by following me on twitter.

Leave a Comment

© 2022 CodingDeft.Com