@samitouri / QOS-React-2 / commits / 1aa9cc6a8b

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