-
Notifications
You must be signed in to change notification settings - Fork 49.9k
Description
Do you want to request a feature or report a bug?
Feature
What is the current behavior?
A component can only access via this.context anything defined in childContextTypes of the parent and contextTypes of the child
If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem via https://jsfiddle.net or similar (template: https://jsfiddle.net/reactjs/69z2wepo/).
N/A
What is the expected behavior?
Would like a way to take all the context available regardless of contextTypes and also pass down, via context, variables not defined in childContextTypes - similar to how propTypes only is for validation
Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?
v15.3.1
Use case:
I have a Portal component that renders its child into a div at the end of the body using ReactDOM-useful for fixed positioned components that you don't want to be in the stacking context of the parent. It works well until you have to pass down context because the context comes from an owner component not being rendered in the new HTML element
import React, { Children, PureComponent, PropTypes } from 'react';
import { unmountComponentAtNode, render } from 'react-dom';
// renders children at the end of the body
export default class Portal extends PureComponent {
static propTypes = {
children: PropTypes.node.isRequired
};
componentDidMount() {
this._el = document.createElement('div');
document.body.appendChild(this._el);
this.renderIntoEl();
}
renderIntoEl = () => {
const { children } = this.props;
render(Children.only(children), this._el);
};
componentDidUpdate({ children }) {
if (children !== this.props.children) {
this.renderIntoEl();
}
}
componentWillUnmount() {
unmountComponentAtNode(this._el);
document.body.removeChild(this._el);
}
render() {
return null;
}
}
I would like to be able to pass down all context available to Portal to the tree rendered in the body tag, something like this
import React, { Children, PureComponent, PropTypes } from 'react';
import { unmountComponentAtNode, render } from 'react-dom';
class ContextProvider extends PureComponent {
static propTypes = {
context: PropTypes.object,
children: PropTypes.node.isRequired
};
getChildContext() {
return this.props.context;
}
render() {
return Children.only(this.props.children);
}
}
// renders children at the end of the body
export default class Portal extends PureComponent {
static propTypes = {
children: PropTypes.node.isRequired
};
// we need to receive the context
static contextTypes = {};
componentDidMount() {
this._el = document.createElement('div');
document.body.appendChild(this._el);
this.renderIntoEl(this.props.children, this.context);
}
renderIntoEl = (children, context) => {
render(
<ContextProvider context={context}>
{Children.only(children)}
</ContextProvider>,
this._el
);
};
componentWillReceiveProps({ children }, nextContext) {
if (children !== this.props.children || nextContext !== this.context) {
this.renderIntoEl(children, nextContext);
}
}
componentWillUnmount() {
unmountComponentAtNode(this._el);
document.body.removeChild(this._el);
}
render() {
return null;
}
}