react-force-graph icon indicating copy to clipboard operation
react-force-graph copied to clipboard

ReferenceError: window is not defined

Open redochka opened this issue 5 years ago • 6 comments

Using this within a nextjs app and getting this error:

ReferenceError: window is not defined

I am just trying basic examples:

<ForceGraph2D graphData={genRandomTree()} width={444} height={1111} />

redochka avatar Feb 13 '20 17:02 redochka

@redochka thanks for reaching out.

This is because nextjs is running in SSR (Server-Side Rendering) mode, which is not compatible with this module because it doesn't provide a window environment. You should bypass SSR when rendering a part of the React DOM that includes this component.

Further, if you're getting this error at import time, you should also turn the import into dynamic so it doesn't fail the build: https://nextjs.org/docs/advanced-features/dynamic-import

vasturiano avatar Feb 19 '20 23:02 vasturiano

If anybody else runs into this issue using react-force-graph with Gatsby like I did, here's how I fixed it.

Install https://github.com/gregberge/loadable-components

npm install @loadable/component

Create a component for your force graph (forceGraph.js)

import { ForceGraph2D } from "react-force-graph"

export default ForceGraph2D

And import it with loadable-components to use as seen in the documentation. const ForceGraph = loadable(() => import('./forceGraph'))

connorwaslo avatar May 29 '20 22:05 connorwaslo

Solved it Here https://github.com/vasturiano/react-force-graph/issues/136#issuecomment-664213307

alitourani avatar Jul 27 '20 08:07 alitourani

Thanks - using loadable-components works for gatsby.

But I am having problems using the react Effect hook. I am trying to recreate this codepen (#25) but with loadable.

import loadable from '@loadable/component'
const ForceGraph2D = loadable(() => import('./forceGraph2d'))

function Graph(props) {
  const forceRef = useRef(null);
  useEffect(() => {
    forceRef.current.d3Force("charge").strength(-4000);
  });
  return (
    <ForceGraph2D
      graphData={props.graphData}
      ref={forceRef}
    />
  );
}

Error in the useEffect hook as forceRef.current is undefined. I am pretty sure this is caused by loadable but not sure exactly why. Any ideas or alternative solutions to changing d3Force settings?

ahmedhosny avatar Dec 18 '20 04:12 ahmedhosny

What you can do is instead load your Graph functional component using loadable, and inside that file load ForceGraph2D with a regular import.

In your graph file (./components/graph):

import ForceGraph2D from 'react-force-graph-2d';

function Graph(props) {
  const forceRef = useRef(null);
  useEffect(() => {
    forceRef.current.d3Force("charge").strength(-4000);
  });
  return (
    <ForceGraph2D
      graphData={props.graphData}
      ref={forceRef}
    />
  );
}

Then where you call the graph in your app:

import loadable from '@loadable/component'
const Graph = loadable(() => import('./components/graph'))

function App() {
  [...]
  return (
    [...]
    <Graph graphData={graphData} />
    [...]
  )
}

I have tested the above solution with next/dynamic so hopefully this technique works with loadable as well.

Scott-Hickmann avatar May 20 '21 17:05 Scott-Hickmann

Anyone on a Next 13, make the component that uses the ForceGraph a client-side component, and dynamically render it from the server component.

I.e.

// ForceGraph.tsx
import ForceGraph2D from 'react-force-graph-2d';

...
// <return component using ForceGraph>
// page.tsx
const DynamicForceGraph = dynamic(() => import('./ForceGraph'), { ssr: false });

...

// <use <DynamicForceGraph> like any other react component>

corbanvilla avatar Jul 21 '23 10:07 corbanvilla