Pass context to the constructor
This should reenable reading this.context from getInitialState. Added a bunch of tests for this too.
Sebastian Markbage committed
Jan 23, 2015 at 10:08 UTC
9abd1133c94288c09512f7cf0b8a0b8136df6da7
5 files changed
+66
-3
src/classic/class/ReactClass.js
+2
-1
@@ -805,7 +805,7 @@ var ReactClass = {
805
* @public
806
*/
807
createClass: function(spec) {
808
- var Constructor = function(props) {
808
+ var Constructor = function(props, context) {
809
// This constructor is overridden by mocks. The argument is used
810
// by mocks to assert on what gets mounted.
811
@@ -815,6 +815,7 @@ var ReactClass = {
815
}
816
817
this.props = props;
818
+ this.context = context;
819
this.state = null;
820
821
// ReactClasses doesn't have constructors. Instead, they use the
src/classic/class/__tests__/ReactClass-test.js
+30
@@ -278,6 +278,36 @@ describe('ReactClass-spec', function() {
278
expect(instance.state.occupation).toEqual('clown');
279
});
280
281
+ it('renders based on context getInitialState', function() {
282
+ var Foo = React.createClass({
283
+ contextTypes: {
284
+ className: React.PropTypes.string
285
+ },
286
+ getInitialState() {
287
+ return { className: this.context.className };
288
+ },
289
+ render() {
290
+ return <span className={this.state.className} />;
291
+ }
292
+ });
293
+
294
+ var Outer = React.createClass({
295
+ childContextTypes: {
296
+ className: React.PropTypes.string
297
+ },
298
+ getChildContext() {
299
+ return { className: 'foo' };
300
+ },
301
+ render() {
302
+ return <Foo />;
303
+ }
304
+ });
305
+
306
+ var container = document.createElement('div');
307
+ React.render(<Outer />, container);
308
+ expect(container.firstChild.className).toBe('foo');
309
+ });
310
+
311
it('should throw with non-object getInitialState() return values', function() {
312
[['an array'], 'a string', 1234].forEach(function(state) {
313
var Component = React.createClass({
src/core/ReactCompositeComponent.js
+1
-1
@@ -169,7 +169,7 @@ var ReactCompositeComponentMixin = assign({},
169
);
170
171
// Initialize the public class
172
- var inst = new Component(publicProps);
172
+ var inst = new Component(publicProps, publicContext);
173
// These should be set up in the constructor, but as a convenience for
174
// simpler class abstractions, we set them up after the fact.
175
inst.props = publicProps;
src/modern/class/ReactComponentBase.js
+2
-1
@@ -19,8 +19,9 @@ var warning = require('warning');
19
/**
20
* Base class helpers for the updating state of a component.
21
*/
22
-function ReactComponentBase(props) {
22
+function ReactComponentBase(props, context) {
23
this.props = props;
24
+ this.context = context;
25
}
26
27
/**
src/modern/class/__tests__/ReactES6Class-test.js
+31
@@ -98,6 +98,37 @@ describe('ReactES6Class', function() {
98
test(<Foo />, 'SPAN', 'bar');
99
});
100
101
+ it('renders based on context in the constructor', function() {
102
+ class Foo extends React.Component {
103
+ constructor(props, context) {
104
+ super(props, context);
105
+ this.state = { tag: context.tag, className: this.context.className };
106
+ }
107
+ render() {
108
+ var Tag = this.state.tag;
109
+ return <Tag className={this.state.className} />;
110
+ }
111
+ }
112
+ Foo.contextTypes = {
113
+ tag: React.PropTypes.string,
114
+ className: React.PropTypes.string
115
+ };
116
+
117
+ class Outer extends React.Component {
118
+ getChildContext() {
119
+ return { tag: 'span', className: 'foo' };
120
+ }
121
+ render() {
122
+ return <Foo />;
123
+ }
124
+ }
125
+ Outer.childContextTypes = {
126
+ tag: React.PropTypes.string,
127
+ className: React.PropTypes.string
128
+ };
129
+ test(<Outer />, 'SPAN', 'foo');
130
+ });
131
+
132
it('renders only once when setting state in componentWillMount', function() {
133
var renderCount = 0;
134
class Foo extends React.Component {