Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Destroys context #43

Closed
AndrewRayCode opened this issue Mar 24, 2019 · 10 comments
Closed

Destroys context #43

AndrewRayCode opened this issue Mar 24, 2019 · 10 comments

Comments

@AndrewRayCode
Copy link

I'm using redux to connect child elements in my scene.

This one took a few hours to track down. I have a simple component connected to redux, like:

@connect(state => ({}))
class MyFriend extends Component {
  render() {
    return null;
  }
}

If I render it outside a <Canvas>, it works fine:

      <div>
        <MyFriend />
        <Canvas />
      </div>

However if I render it inside a Canvas:

      <div>
        <Canvas>
          <MyFriend />
        </Canvas>
      </div>

Then the app crashes:

Uncaught Invariant Violation: Could not find "store" in the context of "Connect(MyFriend)"

I suspect it's related to the custom rendering here, but I'm still digging into it: https://github.com/drcmda/react-three-fiber/blob/master/src/canvas.js#L197-L204

@AndrewRayCode
Copy link
Author

I tried returning the first argument here but same result so far https://github.com/drcmda/react-three-fiber/blob/master/src/reconciler.js#L237-L242

@AndrewRayCode
Copy link
Author

AndrewRayCode commented Mar 25, 2019

This didn't work either:

Canvas.contextTypes = { store: PropTypes.object };
Canvas.childContextTypes = { store: PropTypes.object };

I'm not sure if this is related to the useEffect() call internally, or the .memo() of the Canvas component?

This works (I think), which should probably give me a clue as to what's going on. It's not ideal:

import { ReactReduxContext, Provider } from 'react-redux';

...

        <ReactReduxContext.Consumer>
          {({ store }) => (
            <Canvas>
              <Provider store={store}>
                 ...
              </Provider>
            </Canvas>
         )}
      </ReactReduxContext.Consumer>

@drcmda
Copy link
Member

drcmda commented Mar 25, 2019

Ah yes, React is not able to do this, sorry. There have been bug issues about this in all reconcilers i know. Here's one from react-konva in which @gaearon says that currently context chokes at the threshold of a renderer in a renderer.

konvajs/react-konva#188

facebook/react#13336

Your solution, forwarding the context, is the only way right now. I very much wish that the React team will fix this.

@drcmda
Copy link
Member

drcmda commented Mar 25, 2019

Btw. Redux 7 is dropping context again (due to various issues), they'll go back to a subscription model. This would allow connect to cross render boundaries. They have a 7 beta out already. (paging @markerikson in case i got this wrong). That was also the reason we pinned redux at version 5 (we use a reconciler at work and once redux went context all blew up).

@markerikson
Copy link

@drcmda : we're dropping propagating state changes via context, but we're still using new context to pass down the store itself. That may not go through different reconcilers correctly.

@drcmda
Copy link
Member

drcmda commented Mar 25, 2019

I had some hopes but that makes sense, so it looks like this won't be fixed anytime soon. I think forwarding context is the only solution currently.

@drcmda drcmda closed this as completed Mar 29, 2019
linonetwo added a commit to linonetwo/electron-react-game-dev-playground that referenced this issue Feb 7, 2020
This reminds me of what I encounter when using react-three-fiber, so I search for solution in react-three-fiber 's issue

pmndrs/react-three-fiber#43
gsimone pushed a commit that referenced this issue Sep 17, 2020
@Tirzono
Copy link
Contributor

Tirzono commented Sep 18, 2020

I made a helper function that forwards a context to work around this issue:

import { useContext, createElement } from 'react';

export const forwardContext = (Context) => (Component) => ({ children, ...props }) => {
    const value = useContext(Context);
    const wrapped = createElement(Context.Provider, { value }, children);
    return createElement(Component, props, wrapped);
};

And then (note that you use WrappedCanvas instead of Canvas:

import { Canvas } from 'react-three-fiber';
import SomeContext from './somewhere';
import { forwardContext } from './helpers';

const WrappedCanvas = forwardContext(SomeContext)(Canvas);

const App = ({ children }) => (
    <WrappedCanvas >
        {children}
    </WrappedCanvas >
);

@JustFly1984
Copy link
Contributor

JustFly1984 commented Nov 12, 2020

@drcmda there is better option described here: https://standard.ai/blog/introducing-standard-view-and-react-three-fiber-context-bridge/

I've used it successfully in my react-three-fiber project.

Could be useful to include it to the library and/or docs

@stephencorwin
Copy link
Member

@JustFly1984
We rolled out a useContextBridge hook in the @react-three/drei package for official use within the react-three-fiber ecosystem.

function SceneWrapper() {
  // bridge any number of contexts
  const ContextBridge = useContextBridge(ThemeContext, GreetingContext)
  return (
    <Canvas>
      <ContextBridge>
        <Scene />
      </ContextBridge>
    </Canvas>
  )
}

function Scene() {
  // we can now consume a context within the Canvas
  const theme = React.useContext(ThemeContext)
  const greeting = React.useContext(GreetingContext)
  return (
    //...
  )
}

It's been working out really well and the api is pretty friendly :)

Pinpickle added a commit to Pinpickle/website that referenced this issue Jun 28, 2021
I noticed that the link to pmndrs/react-three-fiber#43 had a typo in it. This removes the extra `h` from `hhttps`
CodyJasonBennett pushed a commit to pmndrs/website that referenced this issue Jun 28, 2021
I noticed that the link to pmndrs/react-three-fiber#43 had a typo in it. This removes the extra `h` from `hhttps`
@bknill
Copy link

bknill commented Mar 16, 2022

Can anyone tell me how to get the Redux Context in the React App ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants