TutorialsCourses

Using react-beautiful-dnd with Next.JS

NextJS server side renders, which if a library dependencies or requirements, this can mess up how a library operates. One such library is react-beautiful-dnd. It's become the standard drag and drop library but when integrating into a Next.JS app requires one additional piece. That piece is using resetServerContext call.

This needs to be called so that markup from the server doesn't conflict with what the client side library expects.

To make it work we need to create a custom _document file in the pages directory. You can follow the docs for the base _document here https://nextjs.org/docs/advanced-features/custom-document

This is what it looks like.

import Document, { Html, Head, Main, NextScript } from "next/document";

class MyDocument extends Document {
  static async getInitialProps(ctx) {
    const initialProps = await Document.getInitialProps(ctx);
    return { ...initialProps };
  }

  render() {
    return (
      <Html>
        <Head />
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

export default MyDocument;

Then we need to import resetServerContext from react-beautiful-dnd and call it in our getInitialProps before we return.

import { resetServerContext } from "react-beautiful-dnd";

static async getInitialProps(ctx) {
  const initialProps = await Document.getInitialProps(ctx);
	resetServerContext()
  return { ...initialProps }
}

This will work great for most cases, however there is another issue if you are running latest Emotion like version 11 or another CSS-in-JS that requires the HTML to extract styling from. This generally requires a call to renderPage .

Just ensure that you call renderPage is rendered, first then you call Document.getInitialProps. If you do not call these in the correct order then you may receive an unable to find any drag handles from react-beautiful-dnd and none of your dragging will work.

Unable to find any drag handles in the context "0"

Here is what a complete example of a _document file with Emotion 11 and resetServerContext from react-beautiful-dnd looks like.

import Document, { Html, Head, Main, NextScript } from "next/document";
import { extractCritical } from "@emotion/server";
import { resetServerContext } from "react-beautiful-dnd";

export default class MyDocument extends Document {
  static async getInitialProps(ctx) {
    const page = await ctx.renderPage();
    const initialProps = await Document.getInitialProps(ctx);
    const styles = extractCritical(page.html);
    resetServerContext();
    return { ...initialProps, ...page, ...styles };
  }

  render() {
    return (
      <Html lang="en">
        <Head>
          <style
            data-emotion-css={this.props.ids.join(" ")}
            dangerouslySetInnerHTML={{ __html: this.props.css }}
          />
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}