Imperative wrappers can't access current context value in commit phase
See original GitHub issueSometimes we have an imperative wrapper like this:
componentDidMount() {
renderSomethingImperatively(this.props)
}
componentDidUpdate() {
renderSomethingImperatively(this.props)
}
render() {
return null
}
Portals eliminated the need for this for regular DOM jumps. But we still need this for embedding renderers (e.g. react-art does this) and use cases like “Vue inside React”.
For cross-renderer embedding, maybe we could extend portals to do that (https://github.com/facebook/react/issues/13332). There are still imperative use cases for cross-library rendering though.
One thing that becomes annoying is that new context won’t propagate down through this imperative boundary. This is because we don’t maintain a stack in the commit phase. We’re traversing a flat linked list of effects. So we don’t actually know what context value is current by the time componentDidMount or componentDidUpdate fires.
For react-art and friends, this means context from a host app is not accessible. This is quite annoying. You could hack around it with something like
<MyConsumer>
{value =>
<ReactART.Surface>
<MyContext.Provider value={value}>
<Stuff />
</MyContext.Provider>
</ReactART.Surface>
}
</MyConsumer>
But this is neither obvious nor convenient. You have to anticipate all contexts that can get used below.
This seems even less convenient for imperative cases like “Vue inside React”.
componentDidMount() {
renderSomethingImperatively(this.props) // ???
}
componentDidUpdate() {
renderSomethingImperatively(this.props) // ???
}
render() {
// <MyConsumer>{value => ???}</MyConsumer>
return <div />
}
Seems like you could use unstable_read() in getDerivedStateFromProps and that would put it into state so you can use it in lifecycles. So maybe that’s sufficient. It still means you need to be explicit about which contexts you want to remember though.
I wonder if we can find a better solution to these use cases.
Issue Analytics
- State:
- Created 5 years ago
- Reactions:5
- Comments:7 (2 by maintainers)

Top Related StackOverflow Question
Here’s my hacky workaround to this which seems to function but could stand to be generalized:
and a usage example (react-konva):
My personal preference is
MyClass.contextType = MyContext;and the value gets automatically set onthis.contextjust like the old one but for single values. If you use more than one here, we need to have a hard conversation about your context abuse.