Using CodeMirror in NextJS without the Navigator error


Fri Feb 05 2021

If you have tried to implement CodeMirror in a NextJS project, you may have seen an error like this everytime you refresh the page:

Navigator not defined error

Instead of hoping that your user would not refresh the page or removing CodeMirror all together, you could try to fix it. Here's how.

Before starting ensure that you do have react-codemirror and codemirror installed. If not, copy and paste the following within your terminal


// if you have npm

npm i codemirror

npm i react-codemirror

//if you have yarn

yarn add codemirror

yarn add react-codemirror

Dynamic Importing

First, you need to make sure that you import react-codemirror and your desired themes and modes using Dynamic imports. To do this, import the dynamic function from NextJS normally as you would with any other npm/yarn package.


import dynamic from 'next/dynamic'

With this function imported, you can start to dynamically import react-codemirror and it's dependencies. Keep in mind though that you have to dynamically import these outside your exported function. Create a const called CodeMirror and set it equal to the dynamic function. Inside the dynamic function, import the dependencies (e.g. import('codemirror/mode/xml/xml')) and then return with import('react-codemirror'). After you have imported all of these, add an object within the function declaring ssr: false. In the end, it should look something like this:


const CodeMirror = dynamic(() => {
    import('codemirror/mode/xml/xml')
    import('codemirror/mode/javascript/javascript')
    import('codemirror/mode/css/css')
    import('codemirror/mode/markdown/markdown')
    import('codemirror/theme/material-ocean.css')
    return import('react-codemirror')
}, {ssr: false})

Rendering

To include the CodeMirror element within your page/component, you first need to enclose it within brackets. After that, you can include everything else such as the value, options, and the onChange event. E.G.:


{<CodeMirror
    className="editor"
    value={devLog}
    name= "Devlog"
    options={{
      theme: 'mdn-like',
      lineNumbers: true,
      mode: 'markdown'
    }}
    onChange={devLog => setDevLog(devLog)}
/>}

To ensure that it everything looks right and works the way you expect it to work (not having the textarea and editor being in two separate places or a bunch of x's), you should include the following in your _app.js file


import 'codemirror/lib/codemirror.css'

In the end, you and your users should be able to write code or write a markdown blog using CodeMirror without having to worry about refreshing the page only to see an error.