Repository: ueberdosis/tiptap
File: packages/react/src/ReactNodeViewRenderer.tsx (TypeScript)

Code before:
   */
  renderer!: ReactRenderer<unknown, ReactNodeViewProps<T>>

  /**
   * The element that holds the rich-text content of the node.
   */
  contentDOMElement!: HTMLElement | null

  /**
   * Setup the React component.
   * Called on initialization.
   */
  mount() {
    const props = {
      editor: this.editor,
      node: this.node,
      decorations: this.decorations as DecorationWithType[],
      innerDecorations: this.innerDecorations,
      view: this.view,
      selected: false,
      extension: this.extension,
      HTMLAttributes: this.HTMLAttributes,
      getPos: () => this.getPos(),
      updateAttributes: (attributes = {}) => this.updateAttributes(attributes),
      deleteNode: () => this.deleteNode(),
      ref: React.createRef<HTMLElement>(),
    } satisfies ReactNodeViewProps

    if (!(this.component as any).displayName) {
      const capitalizeFirstChar = (string: string): string => {
        return string.charAt(0).toUpperCase() + string.substring(1)
      }

      this.component.displayName = capitalizeFirstChar(this.extension.name)
    }

    const onDragStart = this.onDragStart.bind(this)
    const nodeViewContentRef: ReactNodeViewContextProps['nodeViewContentRef'] = element => {
      if (element && this.contentDOMElement && element.firstChild !== this.contentDOMElement) {
        element.appendChild(this.contentDOMElement)
      }
    }
    const context = { onDragStart, nodeViewContentRef }
    const Component = this.component
    // For performance reasons, we memoize the provider component
    // And all of the things it requires are declared outside of the component, so it doesn't need to re-render
    const ReactNodeViewProvider: React.FunctionComponent<ReactNodeViewProps<T>> = React.memo(componentProps => {
      return (
        <ReactNodeViewContext.Provider value={context}>
          {React.createElement(Component, componentProps)}
        </ReactNodeViewContext.Provider>

Review comment (suggestion):
Consider importing entities from the React module instead of importing the whole React namespace. `import { createRef } from 'react'` insead of `import React from 'react'`

Code after:
   */
  renderer!: ReactRenderer<unknown, ReactNodeViewProps<T>>

  /**
   * The element that holds the rich-text content of the node.
   */
  contentDOMElement!: HTMLElement | null

  /**
   * Setup the React component.
   * Called on initialization.
   */
  mount() {
    const props = {
      editor: this.editor,
      node: this.node,
      decorations: this.decorations as DecorationWithType[],
      innerDecorations: this.innerDecorations,
      view: this.view,
      selected: false,
      extension: this.extension,
      HTMLAttributes: this.HTMLAttributes,
      getPos: () => this.getPos(),
      updateAttributes: (attributes = {}) => this.updateAttributes(attributes),
      deleteNode: () => this.deleteNode(),
      ref: createRef<T>(),
    } satisfies ReactNodeViewProps<T>

    if (!(this.component as any).displayName) {
      const capitalizeFirstChar = (string: string): string => {
        return string.charAt(0).toUpperCase() + string.substring(1)
      }

      this.component.displayName = capitalizeFirstChar(this.extension.name)
    }

    const onDragStart = this.onDragStart.bind(this)
    const nodeViewContentRef: ReactNodeViewContextProps['nodeViewContentRef'] = element => {
      if (element && this.contentDOMElement && element.firstChild !== this.contentDOMElement) {
        element.appendChild(this.contentDOMElement)
      }
    }
    const context = { onDragStart, nodeViewContentRef }
    const Component = this.component
    // For performance reasons, we memoize the provider component
    // And all of the things it requires are declared outside of the component, so it doesn't need to re-render
    const ReactNodeViewProvider: NamedExoticComponent<ReactNodeViewProps<T>> = memo(componentProps => {
      return (
        <ReactNodeViewContext.Provider value={context}>
          {createElement(Component, componentProps)}
        </ReactNodeViewContext.Provider>