エラー内容
Next.js で draft.js を使う際、ほとんどのケースで以下のワーニングがでる。
react-dom.development.js?ac89:67 Warning: Prop `data-offset-key` did not match.
Server: "dhdnd-0-0" Client: "5pfru-0-0"
この状態でエディタに書き込むと以下のエラーが発生する。
Cannot read properties of undefined (reading 'getIn')
原因は最初のワーニングの通りで、サーバーサイドとクライアントサイドでdata-offset-keyの値が違うため。
ただ以下のように editorState の初期値をcreateWithContentを用いて与える場合は出ない?っぽい。なんで?
const [editorState, setEditorState] = useState(EditorState.createWithContent(convertFromRaw(JSON)))
解決方法
単純にssrを回避する。そもそもdraft.jsをssrしなければならないケースがない。と思う。
やり方は思いつく限りで2通りある。このサイトでは後者を採用している。
useEffectを使うパターン
描画のタイミングをマウント後にすることで、ssrを回避する。
import { useEffect, useState } from 'react'
import {Editor, EditorState} from 'draft-js'
const DraftEditor = () => {
const [editorState, setEditorState] = useState<EditorState>(null)
useEffect(() => {
setEditorState(EditorState.createEmpty())
}, [])
return (
<>
{editorState && (
<Editor
editorKey="editor"
editorState={editorState}
onChange={setEditorState}
/>
)}
</>
)
}
Dynamic import を使うパターン
draft.jsを使用しているコンポーネントを Dynamic import で読み込む。その際にオプションでssr を false にして、サーバーサイドレンダリングを無効にする。 import dynamic from 'next/dynamic'
const DraftEditor = dynamic(
() => import('@/components/molecules/DraftEditor'),
{ ssr: false }
)
First Load JS のサイズを減らす意味でも Dynamic import で ssr を無効化するほうがいいと思う。