question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[React 18] hydrateRoot(document, <RemixBrowser />) causes app crash with any scripts that modified DOM before hydration

See original GitHub issue

What version of Remix are you using?

the main branch of remix (hash a759affafe30c8df27e36f6253a1d9a574ebf18d)

Steps to Reproduce

Install the Dark Reader Chrome Extension: https://chrome.google.com/webstore/detail/dark-reader/eimadpbcbfnmbkopoojfekhnkhdbieeh?hl=en-US

  1. Checkout the remix repo (this repo.)
  2. Run yarn playground:new
  3. After finishing, run yarn dev in the newly created playground folder, yarn watch in the root of remix

Expected Behavior

should see Remix Playground, Sign up / Log In buttons with Dark Reader able to run

Actual Behavior

The playground loads for a sec, then when React does hydrateRoot, it fails to load if the Dark Reader Chrome Extension is enabled.

The workaround is to don’t use any chrome extensions that modify the DOM in order to run the playground.

react-dom.development.js:86 Warning: Expected server HTML to contain a matching <meta> in <head>.
    at meta
    at Meta (http://localhost:3000/build/_shared/chunk-EYMZ6H3Z.js:2816:7)
    at head
    at html
    at App
    at RemixRoute (http://localhost:3000/build/_shared/chunk-EYMZ6H3Z.js:2586:3)
    at Routes2 (http://localhost:3000/build/_shared/chunk-EYMZ6H3Z.js:2569:7)
    at Router (http://localhost:3000/build/_shared/chunk-EYMZ6H3Z.js:679:15)
    at RemixCatchBoundary (http://localhost:3000/build/_shared/chunk-EYMZ6H3Z.js:1079:10)
    at RemixErrorBoundary (http://localhost:3000/build/_shared/chunk-EYMZ6H3Z.js:1004:5)
    at RemixEntry (http://localhost:3000/build/_shared/chunk-EYMZ6H3Z.js:2466:12)
    at RemixBrowser (http://localhost:3000/build/_shared/chunk-EYMZ6H3Z.js:3213:27)
printWarning @ react-dom.development.js:86
5react-dom.development.js:14344 Uncaught Error: Hydration failed because the initial UI does not match what was rendered on the server.
    at throwOnHydrationMismatch (react-dom.development.js:14344:9)
    at tryToClaimNextHydratableInstance (react-dom.development.js:14372:7)
    at updateHostComponent$1 (react-dom.development.js:20636:5)
    at beginWork (react-dom.development.js:22373:14)
    at HTMLUnknownElement.callCallback2 (react-dom.development.js:4157:14)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:4206:16)
    at invokeGuardedCallback (react-dom.development.js:4270:31)
    at beginWork$1 (react-dom.development.js:27243:7)
    at performUnitOfWork (react-dom.development.js:26392:12)
    at workLoopSync (react-dom.development.js:26303:5)

react-dom.development.js:11996 Uncaught DOMException: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.
    at removeChildFromContainer (http://localhost:3000/build/entry.client-R32SQO3U.js:7970:23)
    at unmountHostComponents (http://localhost:3000/build/entry.client-R32SQO3U.js:16770:17)
    at commitDeletion (http://localhost:3000/build/entry.client-R32SQO3U.js:16814:13)
    at commitMutationEffects_begin (http://localhost:3000/build/entry.client-R32SQO3U.js:16958:19)
    at commitMutationEffects (http://localhost:3000/build/entry.client-R32SQO3U.js:16946:11)
    at commitRootImpl (http://localhost:3000/build/entry.client-R32SQO3U.js:18515:13)
    at commitRoot (http://localhost:3000/build/entry.client-R32SQO3U.js:18446:13)
    at performSyncWorkOnRoot (http://localhost:3000/build/entry.client-R32SQO3U.js:18067:11)
    at flushSyncCallbacks (http://localhost:3000/build/entry.client-R32SQO3U.js:8615:30)
    at commitRootImpl (http://localhost:3000/build/entry.client-R32SQO3U.js:18590:11)

Issue Analytics

  • State:closed
  • Created a year ago
  • Reactions:12
  • Comments:22 (4 by maintainers)

github_iconTop GitHub Comments

12reactions
ryanyogancommented, Jun 12, 2022

If you upgrade to https://www.npmjs.com/package/react/v/18.2.0-next-a412d787e-20220518 you can do the following:

In your entry.client.tsx file

import { RemixBrowser } from "@remix-run/react";
import { hydrateRoot } from "react-dom/client";

hydrateRoot(document, <RemixBrowser />);

In your entry.server.tsx file

import { PassThrough } from "stream";
import { renderToPipeableStream } from "react-dom/server";
import { RemixServer } from "@remix-run/react";
import { Response } from "@remix-run/node";
import type { EntryContext, Headers } from "@remix-run/node";
import isbot from "isbot";

const ABORT_DELAY = 5000;

export default function handleRequest(
  request: Request,
  responseStatusCode: number,
  responseHeaders: Headers,
  remixContext: EntryContext
) {
  const callbackName = isbot(request.headers.get("user-agent"))
    ? "onAllReady"
    : "onShellReady";

  return new Promise((resolve, reject) => {
    let didError = false;

    const { pipe, abort } = renderToPipeableStream(
      <RemixServer context={remixContext} url={request.url} />,
      {
        [callbackName]() {
          let body = new PassThrough();

          responseHeaders.set("Content-Type", "text/html");

          resolve(
            new Response(body, {
              status: didError ? 500 : responseStatusCode,
              headers: responseHeaders,
            })
          );
          pipe(body);
        },
        onShellError(err: unknown) {
          reject(err);
        },
        onError(error: unknown) {
          didError = true;
          console.error(error);
        },
      }
    );
    setTimeout(abort, ABORT_DELAY);
  });
}

And you should be streaming from the server again on the initial render.

This is just a short-term hack; I pulled this from Kent Dodds’s upcoming Front End Masters course, seems like an awesome one!

9reactions
aaacafe786commented, Jul 27, 2022

I would like to bump this issue, we have upgraded our stack to the latest version of react (18.2.0), we modified entry.server (https://github.com/remix-run/indie-stack/blob/main/app/entry.server.tsx) and entry.client (https://github.com/remix-run/indie-stack/blob/main/app/entry.client.tsx) inline with the latest version of the indie stack.

After deploying to production, we are finding errors: image

If you would like to see a reproduction of the issue, please see here: https://pr-30-osc-academic-hub.fly.dev/

Obviously this diverges slightly from the original issue, as this screenshot demonstrates the error in incognito mode with no extensions installed.

edit -> after doing some further investigation, we have pinpointed one of the extensions causing the issue (loom, screen recorder)

Read more comments on GitHub >

github_iconTop Results From Across the Web

ReactDOM.render is no longer supported in React 18 - Stack ...
react -dom : ReactDOM.hydrate has been deprecated. Using it will warn and run your app in React 17 mode. react-dom : ReactDOM.
Read more >
React v18.0 – React Blog
New features in React 18 don't work without it. hydrateRoot : New method to hydrate a server rendered application. Use it instead of...
Read more >
Migrating your React Router App to Remix
import { RemixBrowser } from "@remix-run/react"; import { hydrate } from "react-dom"; hydrate(<RemixBrowser />, document);. In React 18, you'll use hydrateRoot ...
Read more >
React 18 - New Toys, New Footguns, & New Possibilities.
render(<App tab="home" />);. 2. Moving to hydrateRoot. Similarly, for SSR, ReactDOM.hydrate is no longer a thing. Use hydrateRoot ...
Read more >
React 18 Fundamentals Crash Course 2022 - YouTube
05:48 Setup 07:16 Creating a new React app 09: 18 Understanding files and folders 15:58 Updating to React 18 17:30 What is a...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found