@samitouri / QOS-React-2 / commits / 9abd1133c9

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 {