add count() method to ReactChildren
added ReactChildren.count() to count the number of children, and a test case.
Guangqiang Dong committed
Jun 30, 2014 at 20:53 UTC
1aa9cc6a8b33b6b9f9fcfee12ed812dbae003be7
3 files changed
+85
-2
src/utils/ReactChildren.js
+17
-1
@@ -129,9 +129,25 @@ function mapChildren(children, func, context) {
129
return mapResult;
130
}
131
132
+/**
133
+* Count the number of children that are typically specified as
134
+* `props.children`.
135
+*/
136
+
137
+function forEachSingleChildDummy(traverseContext, child, name, i) {
138
+ return null;
139
+}
140
+
141
+function countChildren(children, context) {
142
+ var numberOfChildren = traverseAllChildren(children, forEachSingleChildDummy,
143
+ null);
144
+ return numberOfChildren;
145
+}
146
+
147
var ReactChildren = {
148
forEach: forEachChildren,
134
- map: mapChildren
149
+ map: mapChildren,
150
+ count: countChildren
151
};
152
153
module.exports = ReactChildren;
src/utils/__tests__/ReactChildren-test.js
+63
@@ -335,4 +335,67 @@ describe('ReactChildren', function() {
335
expect(console.warn.calls.length).toEqual(1);
336
expect(mapped).toEqual({'.$something': zero});
337
});
338
+
339
+ it('should return 0 for null children', function() {
340
+ var numberOfChildren = ReactChildren.count(null);
341
+ expect(numberOfChildren).toBe(0);
342
+ });
343
+
344
+ it('should return 0 for undefined children', function() {
345
+ var numberOfChildren = ReactChildren.count(undefined);
346
+ expect(numberOfChildren).toBe(0);
347
+ });
348
+
349
+ it('should return 1 for single child', function() {
350
+ var simpleKid = <span key="simple" />;
351
+ var instance = <div>{simpleKid}</div>;
352
+ var numberOfChildren = ReactChildren.count(instance.props.children);
353
+ expect(numberOfChildren).toBe(1);
354
+ });
355
+
356
+ it('should count the number of children in flat structure', function() {
357
+ var zero = <div key="keyZero" />;
358
+ var one = null;
359
+ var two = <div key="keyTwo" />;
360
+ var three = null;
361
+ var four = <div key="keyFour" />;
362
+
363
+ var instance = (
364
+ <div>
365
+ {zero}
366
+ {one}
367
+ {two}
368
+ {three}
369
+ {four}
370
+ </div>
371
+ );
372
+ var numberOfChildren = ReactChildren.count(instance.props.children);
373
+ expect(numberOfChildren).toBe(5);
374
+ });
375
+
376
+ it('should count the number of children in nested structure', function() {
377
+ var zero = <div key="keyZero" />;
378
+ var one = null;
379
+ var two = <div key="keyTwo" />;
380
+ var three = null;
381
+ var four = <div key="keyFour" />;
382
+ var five = <div key="keyFiveInner" />;
383
+ // five is placed into a JS object with a key that is joined to the
384
+ // component key attribute.
385
+ // Precedence is as follows:
386
+ // 1. If grouped in an Object, the object key combined with `key` prop
387
+ // 2. If grouped in an Array, the `key` prop, falling back to array index
388
+
389
+ var instance = (
390
+ <div>{
391
+ [{
392
+ firstHalfKey: [zero, one, two],
393
+ secondHalfKey: [three, four],
394
+ keyFive: five
395
+ }]
396
+ }</div>
397
+ );
398
+ var numberOfChildren = ReactChildren.count(instance.props.children);
399
+ expect(numberOfChildren).toBe(6);
400
+ });
401
});
src/utils/traverseAllChildren.js
+5
-1
@@ -180,10 +180,14 @@ var traverseAllChildrenImpl =
180
* @param {?*} children Children tree object.
181
* @param {!function} callback To invoke upon traversing each child.
182
* @param {?*} traverseContext Context for traversal.
183
+ * @return {!number} The number of children in this subtree.
184
*/
185
function traverseAllChildren(children, callback, traverseContext) {
186
if (children !== null && children !== undefined) {
186
- traverseAllChildrenImpl(children, '', 0, callback, traverseContext);
187
+ return traverseAllChildrenImpl(children, '', 0, callback, traverseContext);
188
+ }
189
+ else {
190
+ return 0;
191
}
192
}
193