Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
SSR + CSR using next.js

Whether your component relies on client-side features or you are using 3rd party components that are not designed for server-side rendering, sometimes you'll want to defer rendering until on the client. For our example, we'll be using react-chart-2 to load a Doughnut chart.

Doughnut

You'll need a next project and to install chart.js + react-chartjs-2.

$ npm install --save chart.js react-chartjs-2  

Let's start off by creating a new page. We'll create a new file clientLoadExample.js and load up a new component. This component will create a variable graph, set it to a span html element and return it. So far, next is handling the state and deciding when to render our component.

// /pages/clientLoadExample.js

import React from 'react'
export default class ClientLoadExample extends React.Component {
  render() {
    let graph;
    graph = <span> Server </span>;
    return graph;
  }
}

Now let's create a flag that will allow us to check whether we are on the server or on the client. We'll access state and set an inClient flag.

export default class ClientLoadExample extends React.Component {
  state = {
    inClient: false
  };
 
  ...
}

After React inserts an instance of a component into the DOM, the componentDidMount() method is triggered. We can use this method to update our inClient flag.

export default class ClientLoadExample extends React.Component {
  state = {
    inBrowser: false
  };
  componentDidMount() {
    this.setState({ inClient: true });
  }  
 
  ...
}

Now we can monitor the state during the rendering of our component. The next time the component is rendered, we'll be able to check our flag; if we are in the client, load our new component. So let's update our render() method.

export default class ClientLoadExample extends React.Component {
...

  render() {
    let graph;
    if (this.state.inClient) {
        var Chart = require( 'react-chartjs-2' );
        graph = <Chart.Doughnut data={data} />;
    } else {
      graph = <span> Server </span>;
    }
    return graph;
  }
}

There you have it! Let's add some data so that our Doughnut doesn't crash! Oh, and here's the full code snippet :)

import React from 'react'

export default class ClientLoadExample extends React.Component {

  state = {
    inClient: false
  };

  componentDidMount() {
    this.setState({ inClient: true });
  }

  render() {
    let graph;
    if (this.state.inClient) {
        var Chart = require( 'react-chartjs-2' );
        graph = <Chart.Doughnut data={data} />;
    } else {
      graph = <span> Server </span>;
    }
    return graph;
  }
}

const data = {
  labels: [
    'Red',
    'Green',
    'Yellow'
  ],
  datasets: [{
    data: [300, 50, 100],
    backgroundColor: [
    '#FF6384',
    '#36A2EB',
    '#FFCE56'
    ],
    hoverBackgroundColor: [
    '#FF6384',
    '#36A2EB',
    '#FFCE56'
    ]
  }]
};
@RaitoBezarius

This comment has been minimized.

Copy link

RaitoBezarius commented Oct 31, 2016

Awesome tip !

@rauchg

This comment has been minimized.

Copy link

rauchg commented Nov 17, 2016

Thanks a lot for this write-up. Another way of doing this is to set a property in getInitialProps:

static getInitialProps ({ req }) {
  return { isServer: req ? true : false } 
}

Then you get this.props.isServer

@taylorsmithgg

This comment has been minimized.

Copy link

taylorsmithgg commented May 18, 2017

This should be documented somewhere other than a gist.
I spent around an hour today trying to get it working.
Thank you so much!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.