While working with useEffect in Next.js, encountering the error 'ReferenceError: document is not defined' is a common issue

I need assistance with getting Bootstrap tooltips to work in my NextJS project. While I have successfully incorporated other Bootstrap components that require JS, implementing tooltips has proven challenging due to the use of document.querySelectorAll in the script provided by Bootstrap's documentation:

var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'))
var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
  return new bootstrap.Tooltip(tooltipTriggerEl)
})

I have explored various solutions such as using

typeof document !== "undefined
and employing useEffect, but it appears that this code is still being executed during SSR. Is there a problem with my implementation of useEffect, or could there be another issue at play? Below is how I've structured my useEffect:

const Page = (props: any) => {

  useEffect(() => {
    var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'))
    var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
      return new bootstrap.Tooltip(tooltipTriggerEl)
    })
  }, []);

  return (...

While I have successfully integrated the rest of Bootstrap into NextJS without any problems, I prefer not to switch to react-bootstrap due to past challenges with that library.

Thank you for your help!

Below are the modified versions utilizing `typeof document !== "undefined":

if (typeof document !== "undefined") {
    let tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'))
    let tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
      return new Tooltip(tooltipTriggerEl)
    })
  }

UPDATE:

With input from the comments, I have resolved the initial issue within the useEffect. However, I am now encountering the same error with the code in bootstrap.js. The error message reads as follows:

error - ReferenceError: document is not defined at enableDismissTrigger (G:\Projects\nextjs\aaip-ts-bs-app\aaip-ts-bs\node_modules\bootstrap\dist\js\bootstrap.js:761:21) at G:\Projects\nextjs\aaip-ts-bs-app\aaip-ts-bs\node_modules\bootstrap\dist\js\bootstrap.js:856:3 at G:\Projects\nextjs\aaip-ts-bs-app\aaip-ts-bs\node_modules\bootstrap\dist\js\bootstrap.js:7:83 at Object. (G:\Projects\nextjs\aaip-ts-bs-app\aaip-ts-bs\node_modules\bootstrap\dist\js\bootstrap.js:10:3)

It seems like the error occurs when the server attempts to execute certain code within bootstrap.js.

I attempted the next/dynamic solution outlined in a medium post: Third solution at the bottom of the post. However, I am unsure about how to import Tooltip in that manner and utilize it within the useEffect hook. The article presents an example of rendering a client-side component, which does not align with my current setup.

If needed, here is the problematic method within Bootstrap's util/component-functions.js file:

/**
   * --------------------------------------------------------------------------
   * Bootstrap (v5.1.3): util/component-functions.js
   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
   * --------------------------------------------------------------------------
   */

  const enableDismissTrigger = (component, method = 'hide') => {
    const clickEvent = `click.dismiss${component.EVENT_KEY}`;
    const name = component.NAME;
    EventHandler.on(document, clickEvent, `[data-bs-dismiss="${name}"]`, function (event) {
      if (['A', 'AREA'].includes(this.tagName)) {
        event.preventDefault();
      }

      if (isDisabled(this)) {
        return;
      }

      const target = getElementFromSelector(this) || this.closest(`.${name}`);
      const instance = component.getOrCreateInstance(target); // Method argument is left, for Alert and only, as it doesn't implement the 'hide' method

      instance[method]();
    });
  };

As evident from line 4, it references document.

A big thank you to @juliomalves in the comments for aiding me with the initial issue, and I appreciate any forthcoming assistance regarding the new challenge!

Answer №1

The original problem has already been resolved in the "UPDATE" section of the question.

For anyone facing issues with the second part (specifically dealing with references to documents in bootstrap.js), here is the solution that worked for me. While it may not be considered best practice, it does compile and function as expected for my project (now including tooltips!)

In _app.js, where I initially imported bootstrap within useEffect, I have made the following replacement:

useEffect(() => {
    async function loadBootstrap() {
      const bootstrap = await import("../node_modules/bootstrap/dist/js/bootstrap");

      var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'))
      var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
        return new bootstrap.Tooltip(tooltipTriggerEl)
      });
    }

    loadBootstrap();
  }, []);

Based on my understanding, because we are directly calling certain parts of the bootstrap library, this must be done client-side within the useEffect hook. To utilize bootstrap.Tooltip, we need to import bootstrap within the useEffect hook and assign it to a variable. All of this is encapsulated within an asynchronous function declared and called within the useEffect hook.

If additional bootstrap js code is needed that references document either directly or indirectly (which is common), it should also be included here.

Furthermore, if this functionality is only required on a specific page rather than across the entire application (_app.js), it can easily be moved accordingly.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Leverage the power of React in tandem with Express

My web site is being created using the Express framework on NodeJS (hosted on Heroku) and I'm utilizing the React framework to build my components. In my project, I have multiple HTML files containing div elements along with React components that can ...

I would like guidance on how to use onClick to toggle the opening and closing of components, and also how to dispatch a close action

i use createSlice from redux toolkit to create my reducers, where I defined the states below is the code for my store in ./root/app/store.js import { configureStore } from "@reduxjs/toolkit"; import calendarReducer from '../features/calenda ...

The TN-Models-FP error message states that it is not allowed to use the `create` model without an associated `entity` model

Utilizing the TN-models-fp library to construct a basic api inspired by the provided examples, here is my implementation in api.ts: import { axios } from '../axios-instance' import { createApi } from '@thinknimble/tn-models-fp' import { ...

Error message: Nextjs encounters hydration issue only in the production environment

I've been facing this issue for hours now. I deployed my Next.js application on Vercel and encountered numerous hydration errors there. Interestingly, in my local development environment, I don't experience any errors at all. I came across sugge ...

Transmitting a custom PDF document through email with React and Node.js

Currently, I am in the process of developing an application designed to streamline the completion of a complex form. The data entered into this form will be stored on a remote database for future reference and editing purposes. Once the form is ready for s ...

"Unable to execute validateOptions as it is not a recognized function

ERROR src/pages/trade/trade-sagas/trade-sagas.unit.test.js ● Test suite failed to run Cannot locate module 'axios' from 'src/pages/trade/trade-sagas/trade-sagas.unit.test.js' 1 | import { runSaga } from "redux-saga"; &g ...

The PubSub feature is not functioning on the client side, however, it is operational on the Graphql playground, an error message displaying "TypeError:

I am currently in the process of developing a Social app utilizing MongoDB, Express, React, Node, Graphql with Apollo. I found a helpful tutorial on freecodecamp which I am following: Link to the video To achieve real-time functionality, I am implementing ...

How to enhance and expand Material-UI components

I am trying to enhance the Tab component using ES6 class in this way: import React from "react"; import {Tab} from "material-ui"; class CustomTab extends Tab { constructor(props){ super(props); } render(){ return super.rende ...

The React application's route is not functioning properly following deployment on IIS

Hey there, I'm a beginner in the world of reactjs and currently struggling with deploying my react app on IIS. After running npm run build, a build folder is generated. I then transferred this folder to my IIS server. However, when I try to access th ...

Sending a CSS class name to a component using Next.js

I am currently in the process of transitioning from a plain ReactJS project to NextJS and I have a question. One aspect that is confusing me is how to effectively utilize CSS within NextJS. The issue I am facing involves a Button component that receives ...

reactjs error: Attempting to utilize the toLowerCase method on an undefined property during double mapping

My issue involves a JSON structure that requires mapping a function twice in a loop to access objects within an array. Once mapped, I need a textbox for searching the data list. However, I am encountering the following error: TypeError: Cannot read proper ...

Encountering the error message "TypeError: setValue is not a function" while trying to pass it as a

Struggling to update the useState() variables by receiving input from a child component nested within another child component. However, encountering an error message when attempting to call either setItem() or setValue() functions from the useState() decla ...

Change the size of a custom cursor on click using React

I have customized the cursor on my react app, but I want to make it animate when the user clicks. Perhaps by decreasing its size or some other effect. The cursor is within a component that I've included in my Index.js file. I am unsure how to create a ...

The React Material-UI Autocomplete feature seems to be having difficulties when paired with Formik

Code snippet written by someone else needs some adjustments. <FormControl className={classes.formControl}> <InputLabel id="combo-box-demo"> {values.type === "forAllCustom ...

The environmental factors in Turbo are crucial for optimizing performance

I'm having trouble accessing an environmental variable from my local .env file in one of my turbo packages. Every time I try to use it, it returns as undefined. My project is using Turbo to manage a monorepo and is built with Next.js/React/Typescript. ...

Removing various chips from Material-UI Autocomplete upon submitting the form

One issue I am currently facing involves a Form with multiple React Material Autocomplete components that utilize multi-select with Chips. After submitting the form, the state of each Autocomplete clears properly, but the Chips remain visible on the screen ...

Effortless Hydration and Efficient Code Splitting in NextJS Application

I understand Lazy Hydration and Code Splitting, but how can I ensure that the split chunk is only downloaded when the component is being hydrated? This is what my code currently looks like import React from 'react'; import dynamic from 'nex ...

React allows for escaping the apostrophe character by using the syntax `&apos;`

I encountered an error on Versel, but not in my local environment. What could be causing this difference? ./src/pages/acl/index.tsx 20:58:47.129 25:80 Error: `'` can be escaped with `&apos;`, `&lsquo;`, `&#39;`, `&rsquo;`. react/n ...

The issue arises when attempting to utilize ExpressJS middleware in conjunction with NextJS Link feature

Incorporating Next with Express routes, I have set up a scenario where /a should only be accessible to authorized individuals, while /b is open to the public. ... other imports... const app = next({ isDev }) const handle = app.getRequestHandler() async f ...

Encountering Issues with NextJS Dynamic SSR: Mobile Devices stuck on loading screen

Issue: The dynamic import feature of Next JS is encountering loading issues specifically on mobile browsers such as Google Chrome and Safari on IOS. Strangely, the functionality works smoothly on desktop browsers like Google Chrome and Mozilla. The projec ...