Reinstantiate editor on changes

We can't dynamically update the content, so we have to recreate the Editor whenever something changes (page loads and updates)
This commit is contained in:
Justin Edmund 2023-07-06 00:42:37 -07:00
parent 9adcd50519
commit 0e5960f6d5

View file

@ -1,4 +1,4 @@
import { ComponentProps, useCallback } from 'react'
import { ComponentProps, useCallback, useEffect, useState } from 'react'
import { useRouter } from 'next/router'
import { useEditor, EditorContent } from '@tiptap/react'
import StarterKit from '@tiptap/starter-kit'
@ -8,6 +8,7 @@ import CustomMention from '~extensions/CustomMention'
import classNames from 'classnames'
import { mentionSuggestionOptions } from '~utils/mentionSuggestions'
import { Editor as TiptapEditor } from '@tiptap/core'
import type { JSONContent } from '@tiptap/core'
import styles from './index.module.scss'
@ -30,6 +31,8 @@ const Editor = ({
const router = useRouter()
const locale = router.locale || 'en'
const [editor, setEditor] = useState<TiptapEditor | undefined>(undefined)
function isJSON(content?: string) {
if (!content) return false
@ -41,6 +44,51 @@ const Editor = ({
return true
}
useEffect(() => {
editor?.destroy()
const newEditor: TiptapEditor = new TiptapEditor({
content: formatContent(content),
editable: editable,
editorProps: {
attributes: {
class: classNames(
{
[styles.editor]: true,
[styles.bound]: bound,
},
className?.split(' ').map((c) => styles[c])
),
},
},
extensions: [
StarterKit,
Link,
CustomMention.configure({
renderLabel({ options, node }) {
return `${node.attrs.id.name[locale] ?? node.attrs.id.granblue_en}`
},
suggestion: mentionSuggestionOptions,
HTMLAttributes: {
class: classNames({
[styles.mention]: true,
}),
},
}),
Youtube.configure({
inline: false,
modestBranding: true,
interfaceLanguage: locale,
}),
],
onUpdate: ({ editor }) => {
const json = editor.getJSON()
if (onUpdate) onUpdate(json)
},
})
setEditor(newEditor)
}, [content])
function formatContent(content?: string) {
if (!content) return ''
if (isJSON(content)) return JSON.parse(content)
@ -59,46 +107,6 @@ const Editor = ({
}
}
const editor = useEditor({
content: formatContent(content),
editable: editable,
editorProps: {
attributes: {
class: classNames(
{
[styles.editor]: true,
[styles.bound]: bound,
},
className?.split(' ').map((c) => styles[c])
),
},
},
extensions: [
StarterKit,
Link,
CustomMention.configure({
renderLabel({ options, node }) {
return `${node.attrs.id.name[locale] ?? node.attrs.id.granblue_en}`
},
suggestion: mentionSuggestionOptions,
HTMLAttributes: {
class: classNames({
[styles.mention]: true,
}),
},
}),
Youtube.configure({
inline: false,
modestBranding: true,
interfaceLanguage: locale,
}),
],
onUpdate: ({ editor }) => {
const json = editor.getJSON()
if (onUpdate) onUpdate(json)
},
})
const setLink = useCallback(() => {
const previousUrl = editor?.getAttributes('link').href
const url = window.prompt('URL', previousUrl)