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

ReferenceError: window is not defined - Server-Side Rendering (SSR) #40

Open
KrzysztofKarol opened this issue Oct 17, 2017 · 15 comments
Open

Comments

@KrzysztofKarol
Copy link
Contributor

How to use this great library properly with Server-Side Rendering (SSR)

ReferenceError: window is not defined

- react-d3-tree.min.js:1 
    [frontend]/[react-d3-tree]/lib/react-d3-tree.min.js:1:4937
  
  - react-d3-tree.min.js:1 
    [frontend]/[react-d3-tree]/lib/react-d3-tree.min.js:1:4899
  
  - react-d3-tree.min.js:1 e.exports
    [frontend]/[react-d3-tree]/lib/react-d3-tree.min.js:1:5409

return window&&document&&document.all&&!window.atob

@bkrem
Copy link
Owner

bkrem commented Oct 17, 2017

Hi @KrzysztofKarol, thank you for reporting this! I was actually unaware of how/if this library worked with SSR.
The source doesn't make any reference to document/window, so seems to be a bundling/dependency issue, will look into this after work today.

As a workaround until this is implemented you could maybe render the tree on componentDidMount to ensure it renders in the client?

@bkrem bkrem added the SSR label Oct 17, 2017
@KrzysztofKarol
Copy link
Contributor Author

KrzysztofKarol commented Oct 17, 2017

Hi @bkrem Thank you for your almost instantaneous answer.
Yes, I checked that too.
I built it without UglifyJsPlugin and it's used for

isOldIE = memoize(function() {
	// Test for IE <= 9 as proposed by Browserhacks
	// @see http://browserhacks.com/#hack-e71d8692f65334173fee715c222cb805
	// Tests for existence of standard globals is to allow style-loader
	// to operate correctly into non-standard environments
	// @see https://github.com/webpack-contrib/style-loader/issues/177
	return window && document && document.all && !window.atob;
}),

I investigated problem a little
https://github.com/webpack-contrib/style-loader/blob/67120f8dc831626f466d64513b4e26074e89341b/lib/addStyles.js#L23
Problem occures during import

// react-d3-tree.js
module.exports = function(list, options) {
  // Here DEBUG is not defined
  if (typeof DEBUG !== "undefined" && DEBUG) {
    if (typeof document !== "object") throw new Error("The style-loader cannot be used in a non-browser environment");
  }

  options = options || {};

  options.attrs = typeof options.attrs === "object" ? options.attrs : {};

        // Force single-tag solution on IE6-9, which has a hard limit on the # of <style>
        // tags it will allow on a page
  if (!options.singleton) options.singleton = isOldIE();

@bkrem
Copy link
Owner

bkrem commented Oct 17, 2017

Ahh interesting, thanks for digging into this already.

Seems like the least path of resistance would be to set options.singleton if it's part of the style-loader public API since IE 8 and older isn't supported by the React team anymore anyways.
Otherwise it would be worth working around the style-loader plugin if that gets SSR working.

If you have an idea feel free to put in a PR @KrzysztofKarol, otherwise I'll check this out in detail this evening :)

@KrzysztofKarol
Copy link
Contributor Author

I couldn't find simple and good solution. So i made it very dirty way for now - I used isomorphic-style-loader instead of style-loader.
KrzysztofKarol@f876afe

BTW. I also encountered a problem with react-transition-group. react-d3-tree uses 1.1.3 as external and it's somehow overriding 2.2.1 used by material-ui@next.

@bkrem
Copy link
Owner

bkrem commented Oct 17, 2017

Ok cool, good to hear you found a way. If isomorphic-style-loader seems to do the job I'll move the build pipeline to that.

Ok that's a strange one regarding react-transition-group, might make sense to bundle the dependencies directly rather than using externals in that case.

Thanks for reporting these two already, super useful! 🙌

@bkrem bkrem added this to the v1.6.0 milestone Oct 18, 2017
@bkrem bkrem removed this from the v1.6.0 milestone Oct 26, 2017
@bkrem bkrem closed this as completed Mar 27, 2018
@codemonkeycxy
Copy link

@bkrem @KrzysztofKarol Is this issue fixed? Somehow I'm still seeing the same error during server side rendering.

amazing work by the way, looking forward to using it!

@KrzysztofKarol
Copy link
Contributor Author

Hi @codemonkeycxy!

I wasn't using this lib for months so you have to ask @bkrem directly.

@bkrem
Copy link
Owner

bkrem commented May 30, 2018

Hi @codemonkeycxy,

SSR still isn't technically supported. I spent an entire day at the time tinkering with the isomorphic loader that Krzysztof suggested (and one or two other ones).

I couldn't get a stable version out of it and there were more pressing issues to resolve with the library so I closed this as out of scope (sorry for my lack of explanation when I closed it), since this error is preventable if you await componentDidMount() like so:

class MyTreeComponent extends React.PureComponent {
  state = {
	didMount: false
  }

  componentDidMount() {
	this.setState({
	  didMount: true
	})
  }

  render() {
	<div>{this.state.didMount && <Tree />}</div>
  }
}

I'm aware that this isn't optimal (setState in componentDidMount will cause an extra render call) and adds some boilerplate, but I simply haven't had the time to get the SSR issue resolved recently.

I hope this helps as a workaround for now and I will obviously update the issue once a fix is in place!

@bkrem bkrem reopened this May 30, 2018
@KrzysztofKarol
Copy link
Contributor Author

@codemonkeycxy you can also use npm's package react-no-ssr as a workaround

https://github.com/kadirahq/react-no-ssr/blob/master/src/index.js

@thomashibbard
Copy link

thomashibbard commented Jul 10, 2018

@KrzysztofKarol How is this meant to be used?

I see it's a component on NPM now, but I'm still getting window is not defined when used like:

const Root = () => (
  <Provider store={store}>
    <NoSSR>
      <ComponentThatUsesWindow />
    </NoSSR>
  </Provider>
)

@KrzysztofKarol
Copy link
Contributor Author

@thomashibbard I think yes but this repo has latest commit dated on 9 Apr 2016 so I don't know how does it work with latest React versions.
You can report an issue https://github.com/kadirahq/react-no-ssr/issues but I think that no one is maintaining this lib anymore, sadly.

@codemonkeycxy
Copy link

@thomashibbard same window not defined issue even with NoSSR. I finally got it working by doing a inline import

const Tree = require('react-d3-tree').Tree;
return (
  <div style={{width: '100vw', height: '100vh'}}>
    <Tree data={data} onClick={this.onClick} />
  </div>
);

@HACHIMIam
Copy link

let Tree = ' '
class MyComponent extends React.PureComponent {
   state = {
   	redender: false
   };
   async componentDidMount() {
   	let res = await import("react-d3-tree");
   	Tree = res.Tree;
   	this.setState({ redender: true, window });
   }
   render() {
   	return <div style={{ height: 1000, width: 1000 }}>{this.state.redender && <Tree data={myTreeData} />}</div>;
   }
}

this worked for me

@Zunaib
Copy link

Zunaib commented Oct 16, 2019

If anyone is still strugling ?

For Imports
if (canUseDOM()) {
const ReactD3Tree = require('react-d3-tree');
Tree = ReactD3Tree.default;
}

For Usage
if (!canUseDOM()) return null;
return (

);

Function (canUseDOM)
export function canUseDOM() {
return !!(typeof window !== 'undefined' && window.document && window.document.createElement);
}

@gerald-menong
Copy link

Any update with integration of this to Gatsby?

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

7 participants