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

.currentDispatcher gets set to null when calling ReactDOMServer from ReactDOM #14022

Closed
NickDubelman opened this issue Oct 29, 2018 · 11 comments
Closed

Comments

@NickDubelman
Copy link

I happened to notice that React will throw Hooks can only be called inside the body of a function component if a sibling element calls ReactDOMServer.renderToStaticMarkup. I have a fiddle that shows this behavior (I think you need to manually open your console to see the error).

If you wrap the sibling element in a component or even just assign it a variable, this issue does not occur.

It's easy to get around and is a pretty specific bug, but why might this be happening?

@sophiebits sophiebits changed the title Weird Hooks issue when sibling element calls ReactDOMServer function .currentDispatcher gets set to null when calling ReactDOMServer from ReactDOM Oct 30, 2018
@sophiebits
Copy link
Contributor

This happens because when renderToStaticMarkup exits, it sets currentDispatcher to null in the shared React package:

ReactCurrentOwner.currentDispatcher = null;

Instead of setting it to its previous value. (ReactFiberScheduler does the same.)

That means that when you call useState in the child component, there is no dispatcher present.

@acdlite Thoughts? Should we restore the old value?

@gaearon
Copy link
Collaborator

gaearon commented Nov 1, 2018

I think we should since it's a legit (even if not recommended) use case to call e.g. renderToStaticMarkup inside a component. At least it has been so far.

@scullabyte
Copy link

For those of you using next.js, the issue was resolved for me (temporarily) by just dropping the custom distDir I had set up in my next.config.js and reverting to .next for my dist

@steabert
Copy link

steabert commented Jan 4, 2019

Is there a simple way to know if a particular commit has been added to a certain React version? I'm using 16.7.0-alpha.2 and as far as I can tell this fix is not part of that release, but I didn't find an easy way to check this. Thanks for any pointers!

@edoardo-bluframe
Copy link

Hey guys!

Still having this error - I think it's this! - on react@16.8.2, SSR, and react-apollo@2.4.1

SSR works fine and the error throws on React.hydrate

Also I am using react-loadable@5.5.0

Here is my index.js

// @flow
/* eslint-disable react/jsx-max-depth */

import "intersection-observer"
import { ApolloProvider } from "react-apollo"
import App from "./app"
import { AppContainer } from "react-hot-loader"
import { BrowserRouter } from "react-router-dom"
import Loadable from "react-loadable"
import React from "react"
import ReactDOM from "react-dom"
import graphql from "api"

const app = document.getElementById("app")

const shell = Component => (
  <ApolloProvider client={graphql}>
    <AppContainer>
      <BrowserRouter>
        <Component />
      </BrowserRouter>
    </AppContainer>
  </ApolloProvider>
)

const render = Component => {
  if (app !== null) {
    // eslint-disable-next-line no-process-env
    if (process.env.NODE_ENV === "development") {
      ReactDOM.render(shell(Component), app)
    } else {
      Loadable.preloadReady().then(() => {
        ReactDOM.hydrate(shell(Component), app)
      })
    }
  }
}

render(App)

// Webpack Hot Module Replacement API
if (module.hot) {
  module.hot.accept("./app", () => {
    // eslint-disable-next-line global-require
    render(require("./app").default)
  })
}

Is anybody else having a similar problem? 😄

@edoardo-bluframe
Copy link

Hey everybody!

Still same error!

I upgraded react, react-dom, react-apollo and everything else to latest yesterday

Then I decided to try useState again and...

As soon as I do SSR hydrate in production it breaks

SSR load works 100% a-okay, and as soon as we hydrate we get a blank page and invariant violation

This is has been happening for months now!

And this issue is already referenced from #13972

I cannot believe it is so edge-case that we cannot fix it??

@joaquindk
Copy link

Hey everybody!

Still same error!

I upgraded react, react-dom, react-apollo and everything else to latest yesterday

Then I decided to try useState again and...

As soon as I do SSR hydrate in production it breaks

SSR load works 100% a-okay, and as soon as we hydrate we get a blank page and invariant violation

This is has been happening for months now!

And this issue is already referenced from #13972

I cannot believe it is so edge-case that we cannot fix it??

@edoardo-bluframe How have you managed to work around this?

@edoardo-bluframe
Copy link

@joaquindk Totally not!

Cannot use hooks on an Apollo SSR project

Really nobody wants to fix it??

@tones31
Copy link

tones31 commented Dec 1, 2021

I am super stuck on this, too.
I am using expo and created a snack which works on their online platform.
https://snack.expo.dev/@tones31/expo-camera-hook-break

But if you download and install/run it, it fails with this hook error. Can't figure out any workaround.

@eaadithya
Copy link

eaadithya commented Jan 26, 2023

I got the same 'Invalid Hook Call' Error. Reached to the point of ReactCurrentDispatcher.current is null. Found out react instance duplication due to having a custom distDir in Next.js (And obviously my mistake)

@edoardo-bluframe
Copy link

FYI I ended up fixing it... by moving all my React SSR projects to NextJS 😄

It does make setting up SSR child's play and the caching features are fantastic

Very glad that I used a manual SSR setup before and got to work out the ins and outs!

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

No branches or pull requests

10 participants