概要
Nextjsでマークダウンエディタを作成するため、react-simplemde-editor
を利用したところ、SSRでは正しく動作しなかったため、CSRで動作させた際のメモです。
日時
2021年4月23日(金)
環境
- OS : macOS BigSur 11.2.2
- node.js : 12.13.1
- React : 16.12.0
- next: 10.0.7
- react-simplemde-editor(EasyMDE) : 4.1.3
- @codemirror/next: 0.16.0
- codemirror: 5.61.0
- codemirror-node": 0.1.0
エラー内容
react-simplemde-editor
を利用しているページに遷移すると、以下のようなエラーが発生する。
これはSSR(Server Side Rendering)をする際に、ブラウザ側にしか存在しないグローバルオブジェクト(navigatorやwindow)を参照しようとすると、発生するエラーです。
Server Error
ReferenceError: navigator is not defined
This error happened while generating the page. Any console logs will be displayed in the terminal window.
解決策: Dynamic Importを使う
Dynamic Importで動的にモジュールを読み込むことがで、この問題を解決できます。
NextjsにはdynamicというモジュールでDynamic Importを利用でき、オプションでSSRを使用しない設定が可能です。
react-simplemde-editor
をSSRなしで、Dynamic Importで読み込むことで、問題の解決ができます。
参考
一方、react-simplemde-editor
をDynamic Importしても、EasyMDE
の静的メソッドを呼び出そうとするとエラーとなります。
import EasyMDE from "easymde";
export const Editor: React.FC<Props> = (props) => {
const [instance, setInstance] = useState<EasyMDE>();
const getInstance = (instance: EasyMDE) => {
setInstance(instance);
};
const insertCodeMde = () => {
if (!instance) return;
EasyMDE.toggleCodeBlock(instance); // ここでエラーが発生します
};
return (
<>
<SimpleMDE
id="editor"
className="editor"
getMdeInstance={getInstance}
onChange={props.onChange}
/>
</>
);
最終的には、react-simplemde-editor
および、EasyMDE
を呼び出しているコンポーネントをDynamic Importで呼び出すことで、エラーを解決しました。
import dynamic from 'next/dynamic'
const Editor = dynamic(() => {
const promise = import("@/components/parts/Editor").then((r) => r.Editor);
return promise;
}, { ssr: false });
まとめ
NextjsではSSRによるエラーがよく発生しますが、Dynamic Import + SSRなしの設定とすることで、問題を解決することができます。