Home > Enterprise >  window is not defined in next js
window is not defined in next js

Time:03-24

some help here I am trying to use react-wysiwyg-editor in my next js app, but it prints an error of window is undefined

import React, { useState } from "react";
import { Editor } from "react-draft-wysiwyg";
import { EditorState } from "draft-js";
import "../node_modules/react-draft-wysiwyg/dist/react-draft-wysiwyg.css";
import classes from "./temps.module.css";

const EmailTemps = () => {
  const [editorState, setEditorState] = useState(EditorState.createEmpty());

  const handleClick = async () => {
    const response = await fetch("/api/sendMail", {
      method: "POST",
      body: JSON.stringify({ editorState }),
      headers: {
        "Content-Type": "application/json",
      },
    });
    const data = await response.json();
    console.log(data.message);
  };

  if (typeof window !== undefined) {
    <div className={classes.nnn}>
      <Editor editorState={editorState} onEditorStateChange={setEditorState} />

      <button onClick={handleClick} className={classes.but}>
        send email
      </button>
    </div>;
  }
};

export default EmailTemps;

i have tried working around this by

if (typeof window !== undefined) {...}

but the error is persisting, i am not sure if i am just not doing it the right way also, i have tried the next/dynamic, but i couldnt dynamically import something from nodemodules

Right now I know that all i am left with is to use useEffect, which i wouldnt want to, if i have a better alternative. my inquiry, is there any better way i can achieve this ?

CodePudding user response:

I think your main problem is not from your own window object but it's from react-draft-wysiwyg which only supports on the client-side.

To fix it, you need to use dynamic import

import dynamic from 'next/dynamic'; 
const Editor = dynamic(
  () => import('react-draft-wysiwyg').then(mod => mod.Editor),
  { ssr: false }
)

The 2nd problem is your window check should be against a string "undefined" instead of undefined

typeof window !== "undefined"

The 3rd problem is you never return your component elements

if (typeof window === "undefined") {
    return null //return nothing on the server-side
}

//return only on the client-side
return <div className={classes.nnn}>
      <Editor editorState={editorState} onEditorStateChange={setEditorState} />
      <button onClick={handleClick} className={classes.but}>
        send email
      </button>
    </div>

The full implementation

import React, { useState } from "react";
import dynamic from 'next/dynamic'; 
const Editor = dynamic(
  () => import('react-draft-wysiwyg').then(mod => mod.Editor),
  { ssr: false }
)
import { EditorState } from "draft-js";
import "../node_modules/react-draft-wysiwyg/dist/react-draft-wysiwyg.css";
import classes from "./temps.module.css";

const EmailTemps = () => {
  const [editorState, setEditorState] = useState(EditorState.createEmpty());

  const handleClick = async () => {
    const response = await fetch("/api/sendMail", {
      method: "POST",
      body: JSON.stringify({ editorState }),
      headers: {
        "Content-Type": "application/json",
      },
    });
    const data = await response.json();
    console.log(data.message);
  };

  if (typeof window === "undefined") {
    return null //return nothing on the server-side
}

//return only on the client-side
return <div className={classes.nnn}>
      <Editor editorState={editorState} onEditorStateChange={setEditorState} />
      <button onClick={handleClick} className={classes.but}>
        send email
      </button>
    </div>
  }
};

export default EmailTemps;

CodePudding user response:

I have solved this problem by re-using next/dynamic, in the component where i am using EmailTemps like below

import dynamic from 'next/dynamic'
import styles from '../styles/Home.module.css'

export default function Home() {

  const EmailEditor = dynamic( ()=> {
    return import('../comps/emailtemps');
  }, { ssr: false } );

  return (
    <div className={styles.container}>
     <EmailEditor />
    </div>
  )
}

and it just worked, thank you guys, however in the client console, it prints this error

next-dev.js?3515:32 Warning: Can't call setState on a component that is not yet mounted. This is a no-op, but it might indicate a bug in your application. Instead, assign to `this.state` directly or define a `state = {};` class property with the desired state in the r component.

kindly help how i can go about this now

  • Related