-
Notifications
You must be signed in to change notification settings - Fork 49.1k
Description
Sometimes 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 (#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.