'reveal.js: ReferenceError: navigator is not defined on fresh install

I am trying to use reveal.js in my React.js/Next.js website based on this https://revealjs.com/installation/#installing-from-npm

The error I get is:

Server Error

ReferenceError: navigator is not defined
This error happened while generating the page. Any console logs will be displayed in the terminal window.
Source

external%20%22reveal.js%22 (1:0) @ eval

> 1 | module.exports = require("reveal.js");

I read through the entire reveal site and searched, there is no reference to navigator or dependencies anywhere.

This is my code, (the CSS is included in my _app.js):

import Head from 'next/head'
import Link from 'next/link'
import ContainerFull from '../components/container-full'
import MoreStories from '../components/more-stories'
import HeroPost from '../components/hero-post'
import Intro from '../components/intro'
import Layout from '../components/layout'
import { getHomePage, getHomeSlides } from '../lib/api'
import { CMS_NAME } from '../lib/constants'
import Header from '../components/header'
import dynamic from 'next/dynamic'

const MySlides = dynamic(
  () => import('../components/slides'),
  { ssr: false }
)

export default function Page( {page, artwork} ) {
   return (
    <>
      <Layout>
        <Head>
          <title>{ page.seo.title }</title>
          <meta name="description" content={page.seo.metaDesc} />
        </Head>
        <Header />
        <ContainerFull>
          <h1>{ page.title }</h1>
          <MySlides />
          <div dangerouslySetInnerHTML={{ __html: page.content }} />

          {artwork.nodes && artwork.nodes.map((arts) => (
            <span>{arts.title}</span>
          ))}
        </ContainerFull>
      </Layout>
    </>
  )
}

export async function getStaticProps({ params }) {
  const data = await getHomePage()
  console.log(data)
  const art = await getHomeSlides()
  console.log(art)

  return {
    props: {
      page: data,
      artwork: art,
    },
  }
}

slides.js file

import Reveal from 'reveal.js'
import Markdown from 'reveal.js/plugin/markdown/markdown.esm.js'
import React, { useEffect } from "react"

const MySlides = () => {
  useEffect(() => {
    let deck = new Reveal({
        plugins: [ Markdown ]
    })
    deck.initialize()
  })

  return (
    <div>SlideShow</div>
  )
}

export default MySlides


Solution 1:[1]

Since Reveal and Markdown are client side modules which depend on navigator object, it's incorrect to import it in the first two lines. Instead, they should be imported in the useEffect block, as the block will be run in the client side according to the document at https://nextjs.org/docs/basic-features/data-fetching/client-side.

This is what works for me:

import { useEffect } from "react"

const MySlides = () => {
  useEffect(() => {
    // This will be executed in the browser (client-side).
    const clientSideInitialization = async () => {
      // load modules in browser
      const Reveal = await (await import("reveal.js")).default
      const Markdown = await (await import("reveal.js/plugin/markdown/markdown.esm")).default
      const deck = new Reveal({
        plugins: [Markdown]
      })
      deck.initialize()
    }
    clientSideInitialization()
  })

  return (
    <div>SlideShow</div>
  )
}

export default MySlides

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Tian Chen