Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React context implementation for Tiptap #4192

Merged
merged 9 commits into from
Jul 11, 2023

Conversation

bdbch
Copy link
Contributor

@bdbch bdbch commented Jul 8, 2023

Please describe your changes

This PR adds few new features to the React package - mainly:

  • <EditorProvider />: This now creates a react context and the editor instance and passes it through to child components
  • useCurrentEditor(): Is used to get the current wrapping editor

so instead of doing

const MyEditor = () => {
  const editor = useEditor({
    extensions: [...],
    content: `...`,
  })

  if (!editor) {
    return null
  }

  return (
    <>
      <EditorContent editor={editor} />
      <MyFloatingMenu editor={editor} />
      <MyBubbleMenu editor={editor} />
    </>
  )
}

you can now do

const MyEditor = () => {
  return (
    <EditorProvider extensions={[...]} content={`...`}>
      <MyFloatingMenu />
      <MyBubbleMenu />
    </EditorProvider>
  )
}

How did you accomplish your changes

  1. Created a Context, hooks and a wrapping provider component
  2. Added some functionality to the FloatingMenu and BubbleMenu to consume the provider if no editor is provided via props

How have you tested your changes

I tried the default demo and a demo with custom node views and both worked fine.

How can we verify your changes

Check out the deployment preview - if you can't find a difference then everything should be fine.

Checklist

  • The changes are not breaking the editor
  • Added tests where possible
  • Followed the guidelines
  • Fixed linting issues

@bdbch bdbch requested a review from svenadlung as a code owner July 8, 2023 08:41
@bdbch bdbch self-assigned this Jul 8, 2023
@netlify
Copy link

netlify bot commented Jul 8, 2023

Deploy Preview for tiptap-embed ready!

Name Link
🔨 Latest commit 9201067
🔍 Latest deploy log https://app.netlify.com/sites/tiptap-embed/deploys/64ad2ed65cc17f0008fc8613
😎 Deploy Preview https://deploy-preview-4192--tiptap-embed.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

@bdbch bdbch merged commit d689e2d into develop Jul 11, 2023
14 checks passed
@bdbch bdbch deleted the feature/react-context-implementation branch July 11, 2023 16:20
andrewlu0 pushed a commit to trybaseplate/tiptap that referenced this pull request Oct 20, 2023
* feat(react): add react context implementation

* chore(docs): updated react docs & demos for new context

* chore(docs): added slot docs

* chore(docs): fix typo

* chore(react): use correct editor package

* fix typo in react installation docs

* update react typings to latest version

* fix types

---------

Co-authored-by: bdbch <dominik@bdbch.com>
@romellem
Copy link

romellem commented Aug 1, 2024

What purpose is the <EditorConsumer> serving in the <EditorProvider>? That component already has the editor instance - it came from the useEditor() call, and in fact we are already passing it to the EditorContext.Provider.

That seems unnecessary?

That is, can we go from this

export function EditorProvider({
  children, slotAfter, slotBefore, ...editorOptions
}: EditorProviderProps) {
  const editor = useEditor(editorOptions)

  if (!editor) {
    return null
  }

  return (
    <EditorContext.Provider value={{ editor }}>
      {slotBefore}
      <EditorConsumer>
        {({ editor: currentEditor }) => (
          <EditorContent editor={currentEditor} />
        )}
      </EditorConsumer>
      {children}
      {slotAfter}
    </EditorContext.Provider>
  )
}

To this?

export function EditorProvider({
  children, slotAfter, slotBefore, ...editorOptions
}: EditorProviderProps) {
  const editor = useEditor(editorOptions)

  if (!editor) {
    return null
  }

  return (
    <EditorContext.Provider value={{ editor }}>
      {slotBefore}
      {/* Instead use `editor` directly */}
      <EditorContent editor={editor} />
      {children}
      {slotAfter}
    </EditorContext.Provider>
  )
}

Unless there is something I'm missing.

Thanks!

@bdbch
Copy link
Contributor Author

bdbch commented Aug 3, 2024

You can pass in the editor instance from useEditor like this, yes. The consumer is only used to avoid prop drilling with the editor prop deeper in the component tree. (Similar how you can get the editor down the component tree via const { editor } = useCurrentEditor.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants