NextJS issue with server side rendering with react-d3-tree

2.1k Views Asked by At

To start off, I have looked at issue number 40 and 95 on the react-d3-tree github I don't see anything on StackOverflow that would help me. I am trying to implement the parseJSON method so I can take my own JSON file from the project folder and then generate a tree diagram.

Let's start from what I did in the beginning. I copy pasted the example code which worked for 2 seconds before crashing. Reason? Server Side Rendering. Great, so then I find this from NextJS which allows me to disable SSR for some components. Hey, now the example code is working. Let's try the example code where they use external data! Nope, it can't find the parseJSON method. I have no idea what to do, can't find anything to fix this. I am trying to import this function that has some issue with SSR, but because it isn't a component I am not able to import it using dynamic, and I can't import normally because it causes a "window is not defined" error because of SSR. The following are my main two files.

DynamicComponent.js [Version 1]

import dynamic from 'next/dynamic';

const Tree = dynamic(
  () => import('react-d3-tree'),
  { ssr: false },
);

export default Tree;

DynamicComponent.js [Version 2]

import dynamic from 'next/dynamic';

export const Tree = dynamic(
  () => import('react-d3-tree'),
  { ssr: false },
);

export const treeUtil = dynamic(
  () => import('react-d3-tree/src/util'),
  { ssr: false },
);

Diagram/index.js

import React from 'react';
import { Tree, treeUtil } from '../DynamicComponent';

const myTreeData = require('../fakeData.json');

class Diagram extends React.PureComponent {
  constructor() {
    super();

    this.state = {
      data: undefined,
    };
  }

  componentWillMount() {
    treeUtil.parseJSON(myTreeData)
      .then((data) => {
        this.setState({ data });
      });
  }

  render() {
    return (
      <div
        id="treeWrapper"
        style={{ width: '50em', height: '20em' }}
      >
        <Tree data={this.state.data} />
      </div>
    );
  }
}

export default Diagram;

Error I Get with Version 1

ReferenceError: treeUtil is not defined

Error I Get with Version 2

TypeError: _DynamicComponent__WEBPACK_IMPORTED_MODULE_1__.treeUtil.parseJSON is not a function

Please StackOverflow, you're my only hope.

2

There are 2 best solutions below

2
On

I guess treeUtil is not a react component, so you can't use dynamic to import it. Just import it normally may be work.

import dynamic from 'next/dynamic';

export const Tree = dynamic(
  () => import('react-d3-tree'),
  { ssr: false },
);

export { default as treeUtil } from 'react-d3-tree/src/util';
0
On

I ran into the same problem with Cytoscape, a similar library (but specifically for graph-network visualization). It took lots of trial and error, but the solution was:

  1. import the component dynamically
  2. remove the import JSON and inline it into a js file. For some stupid reason, that worked for me and was the magic fix. (how big was your JSON file?) Worse-case try copying & pasting into the component itself.

For your component try this:

// convert fakeData.json to fakeData.js
export default {...fake data here };

import React from 'react';
import dynamic from 'next/dynamic'
import myTreeData from 'fakeData';

const Tree = dynamic(
  () => import('./dynamicComponent'),
   { ssr: false }
);

// you can also delineate a loading component;


// converted to hooks for '21
 const Diagram = () => {
 
   const [data,setData] = useState({});


  useEffect(() => {
    treeUtil.parseJSON(myTreeData)
      .then((data) => {
        setData(data);
      })
  },[treeUtil,myTreeData,setData]);


    return (
      <div
        id="treeWrapper"
        style={{ width: '50em', height: '20em' }}
      >
        <Tree data={data} />
      </div>
    );
  }

export default Diagram;