Skip to content

Commit 04fff37

Browse files
refactor(FilterExample): convert to functional component
Converts the FilterExample component from a class-based component to a functional component using React hooks.
1 parent f999cf1 commit 04fff37

File tree

1 file changed

+66
-96
lines changed

1 file changed

+66
-96
lines changed

examples/src/js/FilterExample.jsx

Lines changed: 66 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1,111 +1,81 @@
1-
import React, { Component } from 'react';
1+
import React, { useState, useCallback, useEffect } from 'react';
22
import CheckboxTree from 'react-checkbox-tree';
33

44
import { fileSystem as nodes } from './common.js';
55

6-
class FilterExample extends Component {
7-
state = {
8-
checked: [
9-
'/app/Http/Controllers/WelcomeController.js',
10-
'/app/Http/routes.js',
11-
'/public/assets/style.css',
12-
'/public/index.html',
13-
'/.gitignore',
14-
],
15-
expanded: [
16-
'/app',
17-
],
18-
filterText: '',
19-
filteredNodes: nodes,
20-
};
21-
22-
constructor(props) {
23-
super(props);
24-
25-
this.onCheck = this.onCheck.bind(this);
26-
this.onExpand = this.onExpand.bind(this);
27-
this.onFilterChange = this.onFilterChange.bind(this);
28-
this.filterTree = this.filterTree.bind(this);
29-
this.filterNodes = this.filterNodes.bind(this);
30-
}
31-
32-
onCheck(checked) {
33-
this.setState({ checked });
34-
}
35-
36-
onExpand(expanded) {
37-
this.setState({ expanded });
38-
}
6+
function FilterExample() {
7+
const [checked, setChecked] = useState([
8+
'/app/Http/Controllers/WelcomeController.js',
9+
'/app/Http/routes.js',
10+
'/public/assets/style.css',
11+
'/public/index.html',
12+
'/.gitignore',
13+
]);
14+
const [expanded, setExpanded] = useState(['/app']);
15+
const [filterText, setFilterText] = useState('');
16+
const [filteredNodes, setFilteredNodes] = useState(nodes);
17+
18+
const onCheck = useCallback((checkedValues) => {
19+
setChecked(checkedValues);
20+
}, []);
21+
22+
const onExpand = useCallback((expandedValues) => {
23+
setExpanded(expandedValues);
24+
}, []);
25+
26+
const onFilterChange = useCallback((e) => {
27+
setFilterText(e.target.value);
28+
}, []);
29+
30+
useEffect(() => {
31+
const nodeMatchesSearchString = ({ label }) => (
32+
label.toLocaleLowerCase().indexOf(filterText.toLocaleLowerCase()) > -1
33+
);
3934

40-
onFilterChange(e) {
41-
this.setState({ filterText: e.target.value }, this.filterTree);
42-
}
35+
const filterNodes = (filtered, node) => {
36+
if (nodeMatchesSearchString(node)) {
37+
// Node's label matches the search string
38+
filtered.push(node);
39+
} else {
40+
// Find if any children match the search string or have descendants who do
41+
const filteredChildren = (node.children || []).reduce(filterNodes, []);
42+
43+
// If so, render these children
44+
if (filteredChildren.length > 0) {
45+
filtered.push({ ...node, children: filteredChildren });
46+
}
47+
}
4348

44-
filterTree() {
45-
const { filterText } = this.state;
49+
return filtered;
50+
};
4651

4752
// Reset nodes back to unfiltered state
4853
if (!filterText) {
49-
this.setState({ filteredNodes: nodes });
50-
54+
setFilteredNodes(nodes);
5155
return;
5256
}
5357

54-
this.setState({
55-
filteredNodes: nodes.reduce(this.filterNodes, []),
56-
});
57-
}
58-
59-
filterNodes(filtered, node) {
60-
if (this.nodeMatchesSearchString(node)) {
61-
// Node's label matches the search string
62-
filtered.push(node);
63-
} else {
64-
// Find if any children match the search string or have descendants who do
65-
const filteredChildren = (node.children || []).reduce(this.filterNodes, []);
66-
67-
// If so, render these children
68-
if (filteredChildren.length > 0) {
69-
filtered.push({ ...node, children: filteredChildren });
70-
}
71-
}
72-
73-
return filtered;
74-
}
75-
76-
nodeMatchesSearchString({ label }) {
77-
const { filterText } = this.state;
78-
79-
return label.toLocaleLowerCase().indexOf(filterText.toLocaleLowerCase()) > -1;
80-
}
81-
82-
render() {
83-
const {
84-
checked,
85-
expanded,
86-
filterText,
87-
filteredNodes,
88-
} = this.state;
89-
90-
return (
91-
<div className="filter-container">
92-
<input
93-
className="filter-text"
94-
placeholder="Search..."
95-
type="text"
96-
value={filterText}
97-
onChange={this.onFilterChange}
98-
/>
99-
<CheckboxTree
100-
checked={checked}
101-
expanded={expanded}
102-
nodes={filteredNodes}
103-
onCheck={this.onCheck}
104-
onExpand={this.onExpand}
105-
/>
106-
</div>
107-
);
108-
}
58+
setFilteredNodes(nodes.reduce(filterNodes, []));
59+
}, [filterText]);
60+
61+
return (
62+
<div className="filter-container">
63+
<input
64+
className="filter-text"
65+
placeholder="Search..."
66+
type="text"
67+
value={filterText}
68+
onChange={onFilterChange}
69+
/>
70+
<CheckboxTree
71+
checked={checked}
72+
expanded={expanded}
73+
nodes={filteredNodes}
74+
onCheck={onCheck}
75+
onExpand={onExpand}
76+
/>
77+
</div>
78+
);
10979
}
11080

11181
export default FilterExample;

0 commit comments

Comments
 (0)