The library for web and native user interfaces.
React onlyChild utility.
Small utility that extracts and validates that there is only a single child passed to a React composite component. The benefit here is that we abstract away *how* the children are actually stored while we iterate on different approaches. This way we won't break callsites as we try different ideas. When we settle on a final approach, all of these callsites will still work.
CommitSyncScript committed
Jun 14, 2013 at 16:45 UTC
1112f1a00305626377f0f9402f139622c57be014
2 files changed
+122
src/utils/__tests__/onlyChild-test.js
new
+89
@@ -0,0 +1,89 @@
1
+/**
2
+ * @emails react-core
3
+ * @jsx React.DOM
4
+ */
5
+
6
+"use strict";
7
+
8
+describe('onlyChild', function() {
9
+
10
+ var React;
11
+ var onlyChild;
12
+ var WrapComponent;
13
+
14
+ beforeEach(function() {
15
+ React = require('React');
16
+ onlyChild = require('onlyChild');
17
+ WrapComponent = React.createClass({
18
+ render: function() {
19
+ return (
20
+ <div>
21
+ {onlyChild(this.props.children, this.props.mapFn, this)}
22
+ </div>
23
+ );
24
+ }
25
+ });
26
+ });
27
+
28
+ it('should fail when passed two children', function() {
29
+ expect(function() {
30
+ var instance =
31
+ <WrapComponent>
32
+ <div />
33
+ <span />
34
+ </WrapComponent>;
35
+ onlyChild(instance.props.children);
36
+ }).toThrow();
37
+ });
38
+
39
+ it('should fail when passed nully values', function() {
40
+ expect(function() {
41
+ var instance =
42
+ <WrapComponent>
43
+ {null}
44
+ </WrapComponent>;
45
+ onlyChild(instance.props.children);
46
+ }).toThrow();
47
+
48
+ expect(function() {
49
+ var instance =
50
+ <WrapComponent>
51
+ {undefined}
52
+ </WrapComponent>;
53
+ onlyChild(instance.props.children);
54
+ }).toThrow();
55
+ });
56
+
57
+ it('should fail when key/value objects', function() {
58
+ expect(function() {
59
+ var instance =
60
+ <WrapComponent>
61
+ {{oneThing: <span />}}
62
+ </WrapComponent>;
63
+ onlyChild(instance.props.children);
64
+ }).toThrow();
65
+ });
66
+
67
+
68
+ it('should not fail when passed interpolated single child', function() {
69
+ expect(function() {
70
+ var instance =
71
+ <WrapComponent>
72
+ {<span />}
73
+ </WrapComponent>;
74
+ onlyChild(instance.props.children);
75
+ }).not.toThrow();
76
+ });
77
+
78
+
79
+ it('should return the only child', function() {
80
+ expect(function() {
81
+ var instance =
82
+ <WrapComponent>
83
+ <span />
84
+ </WrapComponent>;
85
+ onlyChild(instance.props.children);
86
+ }).not.toThrow();
87
+ });
88
+
89
+});
src/utils/onlyChild.js
new
+33
@@ -0,0 +1,33 @@
1
+/**
2
+ * @providesModule onlyChild
3
+ */
4
+"use strict";
5
+
6
+var ReactComponent = require('ReactComponent');
7
+
8
+var invariant = require('invariant');
9
+
10
+/**
11
+ * Returns the first child in a collection of children and verifies that there
12
+ * is only one child in the collection. The current implementation of this
13
+ * function assumes that children have been flattened, but the purpose of this
14
+ * helper function is to abstract away the particular structure of children.
15
+ *
16
+ * @param {?object} children Child collection structure.
17
+ * @return {ReactComponent} The first and only `ReactComponent` contained in the
18
+ * structure.
19
+ */
20
+function onlyChild(children) {
21
+ invariant(Array.isArray(children), 'onlyChild must be passed a valid Array.');
22
+ invariant(
23
+ children.length === 1,
24
+ 'onlyChild must be passed an Array with exactly one child.'
25
+ );
26
+ invariant(
27
+ ReactComponent.isValidComponent(children[0]),
28
+ 'onlyChild must be passed an Array with exactly one child.'
29
+ );
30
+ return children[0];
31
+}
32
+
33
+module.exports = onlyChild;