Skip to content

Simplify useEditor React & Vue integration #6988

@nperez0111

Description

@nperez0111

Affected Packages

react, vue-2, vue-3

Version(s)

3.x

Bug Description

No actual bug here, just offering a way to simplify the integrations in the codebase, but I don't want to implement them 😂

Browser Used

Chrome

Code Example URL

No response

Expected Behavior

This is everything that you would need to significantly reduce the code & improve the performance of the React integration, by leveraging the new mounting behavior that I wrote into Tiptap V3:

import { Editor } from '@tiptap/core'
import Document from '@tiptap/extension-document'
import Paragraph from '@tiptap/extension-paragraph'
import Text from '@tiptap/extension-text'
import React, { StrictMode, useMemo, useReducer } from 'react'


export default () => {
  const [render, forceRender] = useReducer(a => a + 1, 0)
  // This is all that useEditor needs to be
  const editor = useMemo(() => {
    return new Editor({
      extensions: [Document, Paragraph, Text],
      content: `
        <p>
          This is a radically reduced version of Tiptap. It has support for a document, with paragraphs and text. That’s it. It’s probably too much for real minimalists though.
        </p>
      `,
      // useEditor can literally just pass in null here
      element: null,
    })
  }, [])

  return (
    <StrictMode>
      {/* this is all that EditorContent needs to be */}
      <div
        ref={el => {
          if (el) {
            console.log('mounting')
            editor.mount({ mount: el })
          } else {
            console.log('unmounting')
            editor.unmount()
          }
        }}
        key={render}
      />
      <button onClick={forceRender}>Render</button>
    </StrictMode>
  )
}

useEditor, would end up just being a wrapper around creating an editor instance. Ideally, you'd have something to destroy the instance on unmount which would just be a useEffect with unmount.

EditorContent would end up just being a div with a ref which either mounts or unmounts the editor instance to that div (it is optional to mount onto that element or append to it, but I'd say it is better default to just mount to that div).

This would avoid all of the tricky stuff I had to write for the useEditor integration, and improve the performance of the editor, by allowing the editor to mount within the same tick that React mounts the element in, rather than the next one. It is also strictmode proof, since refs are meant exactly for this, so triggering a double ref would work correctly (rather than all the tricky timing stuff I had to do).

Additional Context (Optional)

Just a suggestion on how you guys could simplify some of this code.

I also believe that this would generalize to vue-2 & vue-3, but don't care enough to actually test it in anyway.

Dependency Updates

  • Yes, I've updated all my dependencies.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Open SourceThe issue or pull reuqest is related to the open source packages of Tiptap.

    Projects

    Status

    Triaged

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions