Skip to content
This repository has been archived by the owner on Jan 1, 2025. It is now read-only.

Support "context bridging" #140

Closed
jonas-jonas opened this issue May 22, 2020 · 7 comments
Closed

Support "context bridging" #140

jonas-jonas opened this issue May 22, 2020 · 7 comments
Assignees
Labels
enhancement New feature or request

Comments

@jonas-jonas
Copy link

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:

  • Provide a RecoilConsumer that does this or
  • Get access to the underlying context?
@acutmore
Copy link

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.
It might be possible / easier to keep two Recoil stores in sync using the unstable useTransactionSubscription API.

@inlet
Copy link
Contributor

inlet commented Jun 10, 2020

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 AppContext exported as well.

@drarmstr drarmstr added the enhancement New feature or request label Jun 10, 2020
@drarmstr
Copy link
Contributor

drarmstr commented Jun 10, 2020

I wonder if this is something that could be done with the new Snapshot API for sharing state across <RecoilRoot>s... What are the requirements for what you are trying to accomplish?

@yomybaby
Copy link

In case of react-native-navigation, that can be have many react roots. It's need to the way to share state across <RecoilRoot>.

@femesq
Copy link

femesq commented Jul 24, 2020

Was just wondering if instead of exposing AppContext (I mean, if there are really concern on this) exposing and ContextBridging component like @inlet suggests here would be a viable alternative... 🤔

@drarmstr
Copy link
Contributor

Added a comment to #298 to discuss a proposed approach.

@drarmstr drarmstr self-assigned this Aug 4, 2020
@drarmstr drarmstr changed the title Provide a way to allow for "context bridging" Support "context bridging" Aug 4, 2020
drarmstr pushed a commit to drarmstr/Recoil that referenced this issue Aug 4, 2020
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
@drarmstr drarmstr linked a pull request Aug 4, 2020 that will close this issue
drarmstr pushed a commit to drarmstr/Recoil that referenced this issue Aug 6, 2020
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
@drarmstr drarmstr linked a pull request Aug 6, 2020 that will close this issue
mlajtos added a commit to mlajtos/mosaic that referenced this issue Aug 18, 2020
- 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
@drarmstr
Copy link
Contributor

drarmstr commented Aug 21, 2020

Documented new #516 API in #483

AlexGuz23 pushed a commit to AlexGuz23/Recoil that referenced this issue Nov 3, 2022
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
snipershooter0701 pushed a commit to snipershooter0701/Recoil that referenced this issue Mar 5, 2023
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
eagle2722 added a commit to eagle2722/Recoil that referenced this issue Sep 21, 2024
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
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement New feature or request
Projects
None yet
6 participants