Skip to content

Content loss when typing in React NodeView with conditionally rendered NodeViewContent #7425

@NoFearInMyHeart

Description

@NoFearInMyHeart

Affected Packages

@tiptap/react, @tiptap/extension-image, @tiptap/core

Version(s)

3.15.3

Bug Description

When a custom node extension has content: "inline*" and the NodeViewContent component is conditionally rendered in the React NodeView, users can still position their cursor inside the node's content area. However, any text typed in this state is not properly stored in the document.

Steps to reproduce:

  1. Create a custom Image extension with content: "inline*" and a showCaption attribute
  2. In the React NodeView, conditionally render NodeViewContent only when showCaption is true:
// Extension
export const Image = TiptapImage.extend({
  content: "inline*",
  addAttributes() {
    return {
      showCaption: { default: false },
    }
  },
})

// NodeView
function ImageNodeView({ node, editor }) {
  const showCaption = node.attrs.showCaption
  const hasContent = node.content.size > 0
  const shouldShowCaption = showCaption || hasContent

  return (
    <NodeViewWrapper>
      <img src={node.attrs.src} />
      {editor?.isEditable && shouldShowCaption && (
        <NodeViewContent as="div" />
      )}
    </NodeViewWrapper>
  )
}

3. Insert the node with showCaption: false
4. Use arrow keys or click to position cursor next to the image (cursor enters the node's content area)
5. Type some text - it appears visually on screen
6. Check editor.getJSON() - the typed text is NOT in the document (content.size is 0)

### Browser Used

Chrome

### Code Example URL

_No response_

### Expected Behavior

One of the following:

1. When NodeViewContent is not rendered, ProseMirror should prevent the cursor from entering the node's content area
2. Text typed should be stored correctly regardless of whether NodeViewContent is rendered
3. TipTap should provide a warning when a NodeView's schema has content but NodeViewContent is not in the DOM

### Additional Context (Optional)

This issue is particularly problematic for image nodes with optional captions where:
- Captions are allowed but hidden by default
- The caption area should only appear when the user explicitly enables it

The current behavior creates a confusing UX where users can type text that silently disappears when the document is saved or reloaded.

Workaround attempted:
- Always rendering NodeViewContent fixes the content storage issue, but breaks cursor navigation (cursor gets "trapped" inside the image node)
- Adding arrow key handlers to escape the node helps, but mouse click behavior is still problematic

### Dependency Updates

- [x] 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.

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions