@samitouri / QOS-React / commits / 492057c76f

Fix context getting (#8407)

Ben Alpert committed Nov 28, 2016 at 18:33 UTC 492057c76f9afb8e923d054d2a0b42be14a4ccca
3 files changed +93 -6
scripts/fiber/tests-passing.txt
+2
@@ -49,6 +49,8 @@ src/addons/__tests__/renderSubtreeIntoContainer-test.js
49 * should update context if it changes due to setState
50 * should update context if it changes due to re-render
51 * should render portal with non-context-provider parent
52 +* should get context through non-context-provider parent
53 +* should get context through middle non-context-provider layer
54
55 src/addons/__tests__/update-test.js
56 * pushes
src/addons/__tests__/renderSubtreeIntoContainer-test.js
+82
@@ -215,4 +215,86 @@ describe('renderSubtreeIntoContainer', () => {
215 expect(portal.firstChild.innerHTML).toBe('hello');
216 });
217
218 + it('should get context through non-context-provider parent', () => {
219 + var container = document.createElement('div');
220 + document.body.appendChild(container);
221 + var portal = document.createElement('div');
222 +
223 + class Parent extends React.Component {
224 + render() {
225 + return <Middle />;
226 + }
227 + getChildContext() {
228 + return {value: this.props.value};
229 + }
230 + static childContextTypes = {
231 + value: React.PropTypes.string.isRequired,
232 + };
233 + }
234 +
235 + class Middle extends React.Component {
236 + render() {
237 + return null;
238 + }
239 + componentDidMount() {
240 + renderSubtreeIntoContainer(this, <Child />, portal);
241 + }
242 + }
243 +
244 + class Child extends React.Component {
245 + static contextTypes = {
246 + value: React.PropTypes.string.isRequired,
247 + };
248 + render() {
249 + return <div>{this.context.value}</div>;
250 + }
251 + }
252 +
253 + ReactDOM.render(<Parent value="foo" />, container);
254 + expect(portal.textContent).toBe('foo');
255 + });
256 +
257 + it('should get context through middle non-context-provider layer', () => {
258 + var container = document.createElement('div');
259 + document.body.appendChild(container);
260 + var portal1 = document.createElement('div');
261 + var portal2 = document.createElement('div');
262 +
263 + class Parent extends React.Component {
264 + render() {
265 + return null;
266 + }
267 + getChildContext() {
268 + return {value: this.props.value};
269 + }
270 + componentDidMount() {
271 + renderSubtreeIntoContainer(this, <Middle />, portal1);
272 + }
273 + static childContextTypes = {
274 + value: React.PropTypes.string.isRequired,
275 + };
276 + }
277 +
278 + class Middle extends React.Component {
279 + render() {
280 + return null;
281 + }
282 + componentDidMount() {
283 + renderSubtreeIntoContainer(this, <Child />, portal2);
284 + }
285 + }
286 +
287 + class Child extends React.Component {
288 + static contextTypes = {
289 + value: React.PropTypes.string.isRequired,
290 + };
291 + render() {
292 + return <div>{this.context.value}</div>;
293 + }
294 + }
295 +
296 + ReactDOM.render(<Parent value="foo" />, container);
297 + expect(portal2.textContent).toBe('foo');
298 + });
299 +
300 });
src/renderers/shared/fiber/ReactFiberContext.js
+9 -6
@@ -22,6 +22,7 @@ var {
22 } = require('ReactFiberTreeReflection');
23 var {
24 ClassComponent,
25 + HostContainer,
26 } = require('ReactTypeOfWork');
27
28 if (__DEV__) {
@@ -137,12 +138,14 @@ exports.findCurrentUnmaskedContext = function(fiber: Fiber) : Object {
138 'Expected subtree parent to be a mounted class component'
139 );
140
140 - let node : ?Fiber = parent;
141 - while (node) {
142 - if (isContextProvider(fiber)) {
143 - return fiber.stateNode.__reactInternalMemoizedMergedChildContext;
141 + let node : Fiber = fiber;
142 + while (node.tag !== HostContainer) {
143 + if (isContextProvider(node)) {
144 + return node.stateNode.__reactInternalMemoizedMergedChildContext;
145 }
145 - node = node.return;
146 + const parent = node.return;
147 + invariant(parent, 'Found unexpected detached subtree parent');
148 + node = parent;
149 }
147 - return emptyObject;
150 + return node.stateNode.context;
151 };