-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Support "context bridging" #140
Comments
Hi @jonas-jonas. Interesting issue, first time I've come across the ideas around 'context bridging" so have learnt something new 😀. I might be missing something, but with my limited understanding of how Recoil works it doesn't sound like it would be easy/safe to share a context between two different React renderers. |
I'm the author of react-pixi and I'd love to use Recoil for state management. Unfortunately Contexts don't propagate between renderers, Context bridging is a good way to make this possible. I'd love to see Recoil's |
I wonder if this is something that could be done with the new |
In case of |
Added a comment to #298 to discuss a proposed approach. |
Summary: Export RecoilRoot's store via an opaque type to make Context bridging possible. Recoil uses `React.Context` internally, however the context doesn't travel through custom renderers and a Context Bridge is mostly used to solve this problem. Here's an example of a Context bridge I use for ReactPixi: ``` import { Stage, Text } from 'inlet/react-pixi'; import { RecoilContext, useSetRecoilValue } from 'recoil'; import { theme } from './atoms'; const ContextBridge = ({ children, Context, render }) => { return ( <Context.Consumer> {(value) => render(<Context.Provider value={value}>{children}</Context.Provider>)} </Context.Consumer> ); }; const RendererComponent = () => { const theme = useSetRecoilValue(theme); return <Text text={theme.settings} /> } const App = () => ( <ContextBridge Context={RecoilContext} render={(children) => <Stage>{children}</Stage>} > <RendererComponent /> </ContextBridge> ); ``` Proposed API for Recoil to support context briding without exposing the internals of the Recoil store: ``` function RenderingBridge({children}) { const store = useRecoilStore_UNSTABLE(); return ( <CustomRenderer> <RecoilRoot store_UNSTABLE={store}>{children}</RecoilRoot> </CustomRenderer> ); } function MyApp() { return ( <RecoilRoot> ... <RenderingBridge> ... </RenderingBridge> </RecoilRoot> ); } ``` Fixes facebookexperimental#140 Pull Request resolved: facebookexperimental#298 Differential Revision: D22929302 Pulled By: drarmstr fbshipit-source-id: c54d2b2fd12eecca97385428d9cd449525d71632
Summary: Export RecoilRoot's store via an opaque type to make Context bridging possible. Recoil uses `React.Context` internally, however the context doesn't travel through custom renderers and a Context Bridge is mostly used to solve this problem. Here's an example of a Context bridge I use for ReactPixi: ``` import { Stage, Text } from 'inlet/react-pixi'; import { RecoilContext, useSetRecoilValue } from 'recoil'; import { theme } from './atoms'; const ContextBridge = ({ children, Context, render }) => { return ( <Context.Consumer> {(value) => render(<Context.Provider value={value}>{children}</Context.Provider>)} </Context.Consumer> ); }; const RendererComponent = () => { const theme = useSetRecoilValue(theme); return <Text text={theme.settings} /> } const App = () => ( <ContextBridge Context={RecoilContext} render={(children) => <Stage>{children}</Stage>} > <RendererComponent /> </ContextBridge> ); ``` Proposed API for Recoil to support context briding without exposing the internals of the Recoil store: ``` function RenderingBridge({children}) { const store = useRecoilStore_UNSTABLE(); return ( <CustomRenderer> <RecoilRoot store_UNSTABLE={store}>{children}</RecoilRoot> </CustomRenderer> ); } function MyApp() { return ( <RecoilRoot> ... <RenderingBridge> ... </RenderingBridge> </RecoilRoot> ); } ``` Fixes facebookexperimental#140 Pull Request resolved: facebookexperimental#298 Differential Revision: D22929302 Pulled By: drarmstr fbshipit-source-id: e6cbb1c1f6cf3f2bf92a070719a2b71b504d17ea
- focus follows mouse - focused tab has red line, need something more prominent and nicer - hovering unfocused inactive tab, focuses it in background – could be feature, could be bug - sometimes splitter eats `mousemove` event and tab won't get focused (repro: moving cursor really slowly across splitter) - recoil.js is dumb for not having shared state across multiple React roots (there is a issue filed: facebookexperimental/Recoil#140) – faking reactive state for focused tab is really ugly and really-really bad
Summary: NOTE: Please note updated context bridging proposal in D22983479 or D22935480 Export RecoilRoot's store via an opaque type to make Context bridging possible. Recoil uses `React.Context` internally, however the context doesn't travel through custom renderers and a Context Bridge is mostly used to solve this problem. Here's an example of a Context bridge I use for ReactPixi: ``` import { Stage, Text } from 'inlet/react-pixi'; import { RecoilContext, useSetRecoilValue } from 'recoil'; import { theme } from './atoms'; const ContextBridge = ({ children, Context, render }) => { return ( <Context.Consumer> {(value) => render(<Context.Provider value={value}>{children}</Context.Provider>)} </Context.Consumer> ); }; const RendererComponent = () => { const theme = useSetRecoilValue(theme); return <Text text={theme.settings} /> } const App = () => ( <ContextBridge Context={RecoilContext} render={(children) => <Stage>{children}</Stage>} > <RendererComponent /> </ContextBridge> ); ``` Proposed API for Recoil to support context briding without exposing the internals of the Recoil store: ``` function RenderingBridge({children}) { const store = useRecoilStore_UNSTABLE(); return ( <CustomRenderer> <RecoilRoot store_UNSTABLE={store}>{children}</RecoilRoot> </CustomRenderer> ); } function MyApp() { return ( <RecoilRoot> ... <RenderingBridge> ... </RenderingBridge> </RecoilRoot> ); } ``` Fixes facebookexperimental/Recoil#140 Pull Request resolved: facebookexperimental/Recoil#298 Reviewed By: davidmccabe Differential Revision: D22929302 Pulled By: drarmstr fbshipit-source-id: 41c6d8d66d9326da0e1d09583d98934f60ab6ba2
Summary: NOTE: Please note updated context bridging proposal in D22983479 or D22935480 Export RecoilRoot's store via an opaque type to make Context bridging possible. Recoil uses `React.Context` internally, however the context doesn't travel through custom renderers and a Context Bridge is mostly used to solve this problem. Here's an example of a Context bridge I use for ReactPixi: ``` import { Stage, Text } from 'inlet/react-pixi'; import { RecoilContext, useSetRecoilValue } from 'recoil'; import { theme } from './atoms'; const ContextBridge = ({ children, Context, render }) => { return ( <Context.Consumer> {(value) => render(<Context.Provider value={value}>{children}</Context.Provider>)} </Context.Consumer> ); }; const RendererComponent = () => { const theme = useSetRecoilValue(theme); return <Text text={theme.settings} /> } const App = () => ( <ContextBridge Context={RecoilContext} render={(children) => <Stage>{children}</Stage>} > <RendererComponent /> </ContextBridge> ); ``` Proposed API for Recoil to support context briding without exposing the internals of the Recoil store: ``` function RenderingBridge({children}) { const store = useRecoilStore_UNSTABLE(); return ( <CustomRenderer> <RecoilRoot store_UNSTABLE={store}>{children}</RecoilRoot> </CustomRenderer> ); } function MyApp() { return ( <RecoilRoot> ... <RenderingBridge> ... </RenderingBridge> </RecoilRoot> ); } ``` Fixes facebookexperimental/Recoil#140 Pull Request resolved: facebookexperimental/Recoil#298 Reviewed By: davidmccabe Differential Revision: D22929302 Pulled By: drarmstr fbshipit-source-id: 41c6d8d66d9326da0e1d09583d98934f60ab6ba2
Summary: NOTE: Please note updated context bridging proposal in D22983479 or D22935480 Export RecoilRoot's store via an opaque type to make Context bridging possible. Recoil uses `React.Context` internally, however the context doesn't travel through custom renderers and a Context Bridge is mostly used to solve this problem. Here's an example of a Context bridge I use for ReactPixi: ``` import { Stage, Text } from 'inlet/react-pixi'; import { RecoilContext, useSetRecoilValue } from 'recoil'; import { theme } from './atoms'; const ContextBridge = ({ children, Context, render }) => { return ( <Context.Consumer> {(value) => render(<Context.Provider value={value}>{children}</Context.Provider>)} </Context.Consumer> ); }; const RendererComponent = () => { const theme = useSetRecoilValue(theme); return <Text text={theme.settings} /> } const App = () => ( <ContextBridge Context={RecoilContext} render={(children) => <Stage>{children}</Stage>} > <RendererComponent /> </ContextBridge> ); ``` Proposed API for Recoil to support context briding without exposing the internals of the Recoil store: ``` function RenderingBridge({children}) { const store = useRecoilStore_UNSTABLE(); return ( <CustomRenderer> <RecoilRoot store_UNSTABLE={store}>{children}</RecoilRoot> </CustomRenderer> ); } function MyApp() { return ( <RecoilRoot> ... <RenderingBridge> ... </RenderingBridge> </RecoilRoot> ); } ``` Fixes facebookexperimental/Recoil#140 Pull Request resolved: facebookexperimental/Recoil#298 Reviewed By: davidmccabe Differential Revision: D22929302 Pulled By: drarmstr fbshipit-source-id: 41c6d8d66d9326da0e1d09583d98934f60ab6ba2
Since Recoil relies on the context to propagate and store its state, it would be nice to have the ability to bridge this context, if it isn't propagated to all nodes in the tree.
Unfortunately, this is the case with ReactART (and friends) and the only proposed solution (for now) is to bridge the context using a "Consumer" with another "Provider" directly below it. See facebook/react#13336 and in particular this comment: facebook/react#13336 (comment). Recoil does not provide this, AFAICS.
Would it be possible to either:
RecoilConsumer
that does this orThe text was updated successfully, but these errors were encountered: