remix-run / react-router

Declarative routing for React
https://reactrouter.com
MIT License
52.96k stars 10.26k forks source link

[Bug]: isBrowser false when no document.createElement #11315

Open mateusvahl opened 7 months ago

mateusvahl commented 7 months ago

What version of React Router are you using?

6.22.2

Steps to Reproduce

I'm running react-router-dom in Shopify customer account ui environment

This runs on a webworker with a subset javascript API and no access to DOM APIs.

When using useFetcher() , the submit action was throwing an error saying:

router.fetch() was called during the server render, but it shouldn't be. You are likely calling a useFetcher() method in the body of your component. Try moving it to a useEffect or a callback.

After further investigation in the source code, I notice it was related to to isBrowser detection, which expects window.document.createElement !== "undefined" (false in my environment).

A workaround was define createElement before initialise the route, which fixes the detection.

self.document.createElement = () => {  /** empty **/ };

Let me me know if any additional details is needed.

Expected Behavior

isBrowser should not really on window.document.createElement

Actual Behavior

window.document.createElement is undefined, leading isBrowser to be considered false.

mateusvahl commented 2 months ago

If you are using Shopify customer accounts, you can fix it by:

self.window = {};
self.document= {
  createElement = () => {  /** empty **/ };
}

(Remember that window is not accessible in Shopify customer account/webworker, so we "simulate" its presence).

-

It seems that there's very few places in the source code that uses window, we could probably fix it by using self