Skip to content

Commit

Permalink
Merge pull request mui#4548 from oliviertassinari/fix-render-to-layer…
Browse files Browse the repository at this point in the history
…-context

[RenderToLayer] Fix an internal issue with React
  • Loading branch information
oliviertassinari authored Jun 23, 2016
2 parents d4c99fc + 06fdc6e commit 0306629
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 7 deletions.
23 changes: 16 additions & 7 deletions src/internal/RenderToLayer.js
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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 <MuiThemeProvider /> component as a work around for
* https://github.com/facebook/react/issues/6599.
*/

const layerElement = render();
const layerElement = (
<MuiThemeProvider muiTheme={this.context.muiTheme}>
{render()}
</MuiThemeProvider>
);
this.layerElement = unstable_renderSubtreeIntoContainer(this, layerElement, this.layer);
} else {
this.unrenderLayer();
Expand Down
62 changes: 62 additions & 0 deletions test/integration/RenderToLayer/RenderToLayer.spec.js
Original file line number Diff line number Diff line change
@@ -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('<RenderToLayer />', () => {
it('should pass updated muiTheme context if muiTheme context changes', () => {
class Child extends Component {
static contextTypes = {
muiTheme: PropTypes.object.isRequired,
};

render() {
return <div>{this.context.muiTheme.foo}</div>;
}
}

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 <Child />;
};

render() {
return <RenderToLayer render={this.renderLayer} open={true} />;
}
}

const instance = mount(<Parent />);
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');
});
});

0 comments on commit 0306629

Please sign in to comment.