react-force-graph
react-force-graph copied to clipboard
ReferenceError: window is not defined
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 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
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'))
Solved it Here https://github.com/vasturiano/react-force-graph/issues/136#issuecomment-664213307
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?
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.
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>