Skip to content

Commit 687aa51

Browse files
committed
Various cleanup
1 parent 48b270f commit 687aa51

File tree

3 files changed

+87
-83
lines changed

3 files changed

+87
-83
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
### Other
1313

1414
* [#91]: Prevent disconnection between Sass and Less files on build
15+
* [#97]: Some performance optimizations
1516

1617
## [v1.2.4](https://github.com/jakezatecky/react-checkbox-tree/compare/v1.2.3...v1.2.4) (2018-08-29)
1718

src/js/CheckboxTree.js

Lines changed: 57 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -99,20 +99,20 @@ class CheckboxTree extends React.Component {
9999
this.deserializeLists({ checked, expanded });
100100
}
101101

102-
onCheck(node) {
103-
// node is object from TreeNode
102+
onCheck(nodeInfo) {
104103
const { noCascade, onCheck } = this.props;
104+
const node = this.flatNodes[nodeInfo.value];
105105

106-
this.toggleChecked(node, node.checked, noCascade);
107-
onCheck(this.serializeList('checked'), node);
106+
this.toggleChecked(nodeInfo, nodeInfo.checked, noCascade);
107+
onCheck(this.serializeList('checked'), { ...nodeInfo, children: node.self.children });
108108
}
109109

110-
onExpand(node) {
111-
// node is object from TreeNode
110+
onExpand(nodeInfo) {
112111
const { onExpand } = this.props;
112+
const node = this.flatNodes[nodeInfo.value];
113113

114-
this.toggleNode('expanded', node, node.expanded);
115-
onExpand(this.serializeList('expanded'), node);
114+
this.toggleNode(nodeInfo.value, 'expanded', nodeInfo.expanded);
115+
onExpand(this.serializeList('expanded'), { ...nodeInfo, children: node.self.children });
116116
}
117117

118118
onExpandAll() {
@@ -124,26 +124,24 @@ class CheckboxTree extends React.Component {
124124
}
125125

126126
getShallowCheckState(node, noCascade) {
127-
// node is from props.nodes
128127
const flatNode = this.flatNodes[node.value];
129128

130129
if (flatNode.isLeaf || noCascade) {
131130
return flatNode.checked ? 1 : 0;
132131
}
133132

134-
if (node.children.every(child => (this.flatNodes[child.value].checkState === 1))) {
133+
if (this.isEveryChildChecked(node)) {
135134
return 1;
136135
}
137136

138-
if (node.children.some(child => (this.flatNodes[child.value].checkState > 0))) {
137+
if (this.isSomeChildChecked(node)) {
139138
return 2;
140139
}
141140

142141
return 0;
143142
}
144143

145144
getDisabledState(node, parent, disabledProp, noCascade) {
146-
// node is from props.nodes
147145
if (disabledProp) {
148146
return true;
149147
}
@@ -172,27 +170,24 @@ class CheckboxTree extends React.Component {
172170
}
173171

174172
toggleChecked(node, isChecked, noCascade) {
175-
// node is object from TreeNode
176173
const flatNode = this.flatNodes[node.value];
177174

178175
if (flatNode.isLeaf || noCascade) {
179176
// Set the check status of a leaf node or an uncoupled parent
180-
this.toggleNode('checked', node, isChecked);
177+
this.toggleNode(node.value, 'checked', isChecked);
181178
} else {
182-
const { children } = flatNode.self;
183179
// Percolate check status down to all children
184-
children.forEach((child) => {
180+
flatNode.self.children.forEach((child) => {
185181
this.toggleChecked(child, isChecked, noCascade);
186182
});
187183
}
188184
}
189185

190-
toggleNode(key, node, toggleValue) {
191-
this.flatNodes[node.value][key] = toggleValue;
186+
toggleNode(nodeValue, key, toggleValue) {
187+
this.flatNodes[nodeValue][key] = toggleValue;
192188
}
193189

194190
flattenNodes(nodes, parentNode = {}) {
195-
// nodes are from props.nodes
196191
if (!Array.isArray(nodes) || nodes.length === 0) {
197192
return;
198193
}
@@ -241,8 +236,15 @@ class CheckboxTree extends React.Component {
241236
return list;
242237
}
243238

239+
isEveryChildChecked(node) {
240+
return node.children.every(child => this.flatNodes[child.value].checkState === 1);
241+
}
242+
243+
isSomeChildChecked(node) {
244+
return node.children.some(child => this.flatNodes[child.value].checkState > 0);
245+
}
246+
244247
renderTreeNodes(nodes, parent = {}) {
245-
// nodes are props.nodes
246248
const {
247249
disabled,
248250
expandDisabled,
@@ -260,57 +262,51 @@ class CheckboxTree extends React.Component {
260262

261263
const treeNodes = nodes.map((node) => {
262264
const key = `${node.value}`;
263-
264265
const flatNode = this.flatNodes[node.value];
266+
const children = flatNode.isParent ? this.renderTreeNodes(node.children, node) : null;
267+
const nodeDisabled = this.getDisabledState(node, parent, disabled, noCascade);
265268

266-
let children = null;
267-
if (!flatNode.isLeaf) {
268-
children = this.renderTreeNodes(node.children, node);
269-
}
270-
271-
// set checkState here
272-
// this can be "shallow" because checkState is updated for all
273-
// nested children in the recursive call to renderTreeNodes above
269+
// Get the check state after all children check states are determined
274270
flatNode.checkState = this.getShallowCheckState(node, noCascade);
275271

276-
const nodeDisabled = this.getDisabledState(node, parent, disabled, noCascade);
277-
278272
// Show checkbox only if this is a leaf node or showCheckbox is true
279273
const showCheckbox = onlyLeafCheckboxes ? flatNode.isLeaf : flatNode.showCheckbox;
280274

281-
// root of tree has no parent value and is expanded by default
275+
// Render only if parent is expanded or if there is no root parent
282276
const parentExpanded = parent.value ? this.flatNodes[parent.value].expanded : true;
283-
if (parentExpanded) {
284-
return (
285-
<TreeNode
286-
key={key}
287-
checked={flatNode.checkState}
288-
className={node.className}
289-
disabled={nodeDisabled}
290-
expandDisabled={expandDisabled}
291-
expandOnClick={expandOnClick}
292-
expanded={flatNode.expanded}
293-
icon={node.icon}
294-
icons={{ ...defaultIcons, ...icons }}
295-
label={node.label}
296-
lang={lang}
297-
optimisticToggle={optimisticToggle}
298-
isLeaf={flatNode.isLeaf}
299-
showCheckbox={showCheckbox}
300-
showNodeIcon={showNodeIcon}
301-
title={showNodeTitle ? node.title || node.label : node.title}
302-
treeId={this.id}
303-
value={node.value}
304-
onCheck={this.onCheck}
305-
onClick={onClick}
306-
onExpand={this.onExpand}
307-
>
308-
{children}
309-
</TreeNode>
310-
);
277+
278+
if (!parentExpanded) {
279+
return null;
311280
}
312281

313-
return null;
282+
return (
283+
<TreeNode
284+
key={key}
285+
checked={flatNode.checkState}
286+
className={node.className}
287+
disabled={nodeDisabled}
288+
expandDisabled={expandDisabled}
289+
expandOnClick={expandOnClick}
290+
expanded={flatNode.expanded}
291+
icon={node.icon}
292+
icons={{ ...defaultIcons, ...icons }}
293+
label={node.label}
294+
lang={lang}
295+
optimisticToggle={optimisticToggle}
296+
isLeaf={flatNode.isLeaf}
297+
isParent={flatNode.isParent}
298+
showCheckbox={showCheckbox}
299+
showNodeIcon={showNodeIcon}
300+
title={showNodeTitle ? node.title || node.label : node.title}
301+
treeId={this.id}
302+
value={node.value}
303+
onCheck={this.onCheck}
304+
onClick={onClick}
305+
onExpand={this.onExpand}
306+
>
307+
{children}
308+
</TreeNode>
309+
);
314310
});
315311

316312
return (

src/js/TreeNode.js

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ class TreeNode extends React.Component {
1515
expanded: PropTypes.bool.isRequired,
1616
icons: iconsShape.isRequired,
1717
isLeaf: PropTypes.bool.isRequired,
18+
isParent: PropTypes.bool.isRequired,
1819
label: PropTypes.node.isRequired,
1920
lang: languageShape.isRequired,
2021
optimisticToggle: PropTypes.bool.isRequired,
@@ -74,39 +75,43 @@ class TreeNode extends React.Component {
7475
}
7576

7677
onClick() {
78+
const {
79+
checked,
80+
expandOnClick,
81+
isParent,
82+
optimisticToggle,
83+
value,
84+
onClick,
85+
} = this.props;
7786
let isChecked = false;
7887

79-
if (this.props.checked === 1) {
88+
if (checked === 1) {
8089
isChecked = true;
8190
}
8291

8392
// Get partial state based on cascade model
84-
if (this.props.checked === 2) {
85-
isChecked = this.props.optimisticToggle;
93+
if (checked === 2) {
94+
isChecked = optimisticToggle;
8695
}
8796

8897
// Auto expand if enabled
89-
if (!this.props.isLeaf && this.props.expandOnClick) {
98+
if (isParent && expandOnClick) {
9099
this.onExpand();
91100
}
92101

93-
this.props.onClick({
94-
value: this.props.value,
95-
checked: isChecked,
96-
});
102+
onClick({ value, checked: isChecked });
97103
}
98104

99105
onExpand() {
100-
this.props.onExpand({
101-
value: this.props.value,
102-
expanded: !this.props.expanded,
103-
});
106+
const { expanded, value, onExpand } = this.props;
107+
108+
onExpand({ value, expanded: !expanded });
104109
}
105110

106111
renderCollapseButton() {
107-
const { expandDisabled, lang } = this.props;
112+
const { expandDisabled, isLeaf, lang } = this.props;
108113

109-
if (this.props.isLeaf) {
114+
if (isLeaf) {
110115
return (
111116
<span className="rct-collapse">
112117
<span className="rct-icon" />
@@ -151,13 +156,18 @@ class TreeNode extends React.Component {
151156
}
152157

153158
renderNodeIcon() {
154-
const { expanded, icon, icons: { leaf, parentClose, parentOpen } } = this.props;
159+
const {
160+
expanded,
161+
icon,
162+
icons: { leaf, parentClose, parentOpen },
163+
isLeaf,
164+
} = this.props;
155165

156166
if (icon !== null) {
157167
return icon;
158168
}
159169

160-
if (this.props.isLeaf) {
170+
if (isLeaf) {
161171
return leaf;
162172
}
163173

@@ -170,7 +180,6 @@ class TreeNode extends React.Component {
170180

171181
renderBareLabel(children) {
172182
const { onClick, title } = this.props;
173-
174183
const clickable = onClick.toString() !== TreeNode.defaultProps.onClick.toString();
175184

176185
return (
@@ -200,7 +209,6 @@ class TreeNode extends React.Component {
200209
value,
201210
onClick,
202211
} = this.props;
203-
204212
const clickable = onClick.toString() !== TreeNode.defaultProps.onClick.toString();
205213
const inputId = `${treeId}-${String(value).split(' ').join('_')}`;
206214

@@ -240,7 +248,6 @@ class TreeNode extends React.Component {
240248

241249
renderLabel() {
242250
const { label, showCheckbox, showNodeIcon } = this.props;
243-
244251
const labelChildren = [
245252
showNodeIcon ? (
246253
<span key={0} className="rct-node-icon">
@@ -268,11 +275,11 @@ class TreeNode extends React.Component {
268275
}
269276

270277
render() {
271-
const { className, disabled } = this.props;
278+
const { className, disabled, isLeaf } = this.props;
272279
const nodeClass = classNames({
273280
'rct-node': true,
274-
'rct-node-parent': !this.props.isLeaf,
275-
'rct-node-leaf': this.props.isLeaf,
281+
'rct-node-leaf': isLeaf,
282+
'rct-node-parent': !isLeaf,
276283
'rct-disabled': disabled,
277284
}, className);
278285

0 commit comments

Comments
 (0)