From 06fdc6ee11f506a647a49be8866eb9916edfcc74 Mon Sep 17 00:00:00 2001 From: Olivier Tassinari Date: Wed, 22 Jun 2016 19:56:16 +0200 Subject: [PATCH] [RenderToLayer] Fix an internal issue with React --- src/internal/RenderToLayer.js | 23 ++++--- .../RenderToLayer/RenderToLayer.spec.js | 62 +++++++++++++++++++ 2 files changed, 78 insertions(+), 7 deletions(-) create mode 100644 test/integration/RenderToLayer/RenderToLayer.spec.js diff --git a/src/internal/RenderToLayer.js b/src/internal/RenderToLayer.js index c8d499022aeb34..5aac39f63c87e2 100644 --- a/src/internal/RenderToLayer.js +++ b/src/internal/RenderToLayer.js @@ -1,6 +1,8 @@ -import {Component, PropTypes} from 'react'; +import React, {Component, PropTypes} from 'react'; import {unstable_renderSubtreeIntoContainer, unmountComponentAtNode} from 'react-dom'; + import Dom from '../utils/dom'; +import MuiThemeProvider from '../styles/MuiThemeProvider'; // heavily inspired by https://github.com/Khan/react-components/blob/master/js/layered-component-mixin.jsx class RenderToLayer extends Component { @@ -74,6 +76,12 @@ class RenderToLayer extends Component { this.layer = null; } + /** + * By calling this method in componentDidMount() and + * componentDidUpdate(), you're effectively creating a "wormhole" that + * funnels React's hierarchical updates through to a DOM node on an + * entirely different part of the page. + */ renderLayer() { const { open, @@ -103,13 +111,14 @@ class RenderToLayer extends Component { } /** - * By calling this method in componentDidMount() and - * componentDidUpdate(), you're effectively creating a "wormhole" that - * funnels React's hierarchical updates through to a DOM node on an - * entirely different part of the page. + * We use the component as a work around for + * https://github.com/facebook/react/issues/6599. */ - - const layerElement = render(); + const layerElement = ( + + {render()} + + ); this.layerElement = unstable_renderSubtreeIntoContainer(this, layerElement, this.layer); } else { this.unrenderLayer(); diff --git a/test/integration/RenderToLayer/RenderToLayer.spec.js b/test/integration/RenderToLayer/RenderToLayer.spec.js new file mode 100644 index 00000000000000..8985655b5c0e2a --- /dev/null +++ b/test/integration/RenderToLayer/RenderToLayer.spec.js @@ -0,0 +1,62 @@ +/* eslint-env mocha */ +import {assert} from 'chai'; +import React, {Component, PropTypes} from 'react'; +import {mount} from 'enzyme'; +import RenderToLayer from 'src/internal/RenderToLayer'; + +describe('', () => { + it('should pass updated muiTheme context if muiTheme context changes', () => { + class Child extends Component { + static contextTypes = { + muiTheme: PropTypes.object.isRequired, + }; + + render() { + return
{this.context.muiTheme.foo}
; + } + } + + class Parent extends Component { + static childContextTypes = { + muiTheme: PropTypes.object.isRequired, + }; + + state = { + muiTheme: { + zIndex: { + layer: 1, + }, + foo: 'initial', + }, + }; + + getChildContext() { + return { + muiTheme: this.state.muiTheme, + }; + } + + renderLayer = () => { + return ; + }; + + render() { + return ; + } + } + + const instance = mount(); + const portal = document.body.lastChild; + + assert.strictEqual(portal.firstChild.innerHTML, 'initial'); + instance.setState({ + muiTheme: { + zIndex: { + layer: 1, + }, + foo: 'changed', + }, + }); + assert.strictEqual(portal.firstChild.innerHTML, 'changed'); + }); +});