javascriptreactjsnext.jsdisqus

Dynamically load Disqus comments on button click in Next.js


I noticed in Vercel Analytics that when a page has Disqus comments embedded, it drastically decreases the page performance scores. So I want to have a button "Load comments" instead of actual comments and onClick load them.

I'm using the disqus-react npm package as a wrapper, but if there's going to be an implementation without it, it's also fine. I just tried to be as React-native as possible and use existing components instead of adding script blocks.

I found dynamic imports section https://nextjs.org/docs/advanced-features/dynamic-import as well as a few related articles onClick doesn't render new react component., NextJS dynamically add button onClick and What's the right way to do `onClick` in a NextJS component? but they are outdated or about other topics. Also, React 18.2 and NextJS 13.0 are released, so maybe there are new/better ways how to achieve my goal.

So far I have a following code:

import { DiscussionEmbed } from 'disqus-react'

export async function getStaticProps() {
    return {
        props: {
            ...posts.find(post => post.slug == 'my-best-post')
        }
    }
}

export default function Post(props) {
    return <>
        Post text....
        <DiscussionEmbed
            shortname='myid'
            config={        
                omitted for brevity
            }
        />
    </>
}

Dynamic exports official docs article has several options, with disabled SSR, with external library, shall I use both options? As technically I don't need comments to be generated on server.


Solution

  • In order to load the Disqus comments on-demand only, you can dynamically import DiscussionEmbed using next/dynamic with ssr: false. This prevents the component to be loaded during server-side rendering.

    Next, you can use a state variable (let's say showComments) to toggle the rendering of the DiscussionEmbed when the button is clicked. Due to the dynamic import, this will only load the disqus-react code when the click occurs (you can check the devtools Network tab to see the additional requests that are made).

    import { useState } from 'react'
    import dynamic from 'next/dynamic'
    
    // Dynamically import `DiscussionEmbed` on the client-side only
    const DiscussionEmbed = dynamic(
        () => import('disqus-react').then((mod) => mod.DiscussionEmbed),
        { ssr: false }
    )
    
    export default function Post(props) {
        const [showComments, setShowComments] = useState(false)
    
        return <>
            <button onClick={() => setShowComments(true)}>Load Comments</button>
            {showComments && <DiscussionEmbed
                shortname="myid"
                config={{/* Your config here */}}
            />}
        </>
    }