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

Bug: Error when extending DecoratorNode; Element type is invalid: expected a string #6635

Open
dnamme opened this issue Sep 16, 2024 · 2 comments

Comments

@dnamme
Copy link

dnamme commented Sep 16, 2024

I'm trying to create a custom image plugin by extending DecoratorNode. Notably, the same code works with Lexical version 0.5.0 (as seen in older online tutorials) but not in the most recent stable version. I'm using React + JavaScript for the project.

Lexical version: 0.17.1

Steps To Reproduce

  1. Create ImageNode with code below
  2. Create ImagePlugin with code below
  3. Add buttons to dispatch INSERT_IMAGE_COMMAND

Image node code:

import { DecoratorNode } from 'lexical';

export class ImageNode extends DecoratorNode {
  __src;

  static getType() {
    return 'image';
  }

  static clone(node) {
    return new ImageNode(node.__src, node.__key);
  }

  constructor(src, key) {
    super(key);
    this.__src = src;
  }

  createDOM() {
    return document.createElement('div');
  }

  exportDOM() {
    const element = document.createElement('img');
    element.setAttribute('src', this.__src);

    return { element };
  }

  static importDOM() {
    return {
      img: (node) => {
        return {
          conversion: convertImageElement,
          priority: 0,
        };
      },
    };
  }

  updateDOM() {
    return false;
  }

  static importJSON(serializedNode) {
    const { src } = serializedNode;
    const node = $createImageNode({ src });
    return node;
  }

  exportJSON() {
    return {
      src: this.__src,
      type: 'image',
      version: 1,
    };
  }

  decorate() {
    return (
      <img
        nodeKey={this.getKey()}
        src={this.__src}
      />
    );
  }
}

export function $createImageNode({ src }) {
  return new ImageNode(src);
}

export function $isImageNode(node) {
  return node instanceof ImageNode;
}

const convertImageElement = (domNode) => {
  if (domNode instanceof HTMLImageElement) {
    const { src } = domNode;
    const node = $createImageNode(src);
    return { node };
  }

  return null;
};

Plugin code (no error):

import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
import {
  $createParagraphNode,
  $insertNodes,
  $isRootOrShadowRoot,
  COMMAND_PRIORITY_EDITOR,
  createCommand,
} from 'lexical';
import { $createImageNode, ImageNode } from '../../components/nodes/ImageNode';

export default function ImagePlugin() {
  const [editor] = useLexicalComposerContext();

  if (!editor.hasNodes([ImageNode])) {
    throw new Error('Not registered');
  }

  editor.registerCommand(
    INSERT_IMAGE_COMMAND,
    (payload) => {
      const node = $createImageNode(payload);
      $insertNodes([node]);

      return true;
    },
    COMMAND_PRIORITY_EDITOR
  );

  return null;
}

export const INSERT_IMAGE_COMMAND = createCommand('INSERT_IMAGE_COMMAND');

The current behavior

Shows the following error when command is dispatched:

Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

Check the render method of `RichTextPlugin`.
    at createFiberFromTypeAndProps (chunk-3IHV7RO6.js?v=82682a78:20442:23)
    at createFiberFromElement (chunk-3IHV7RO6.js?v=82682a78:20463:23)
    at reconcileSingleElement (chunk-3IHV7RO6.js?v=82682a78:10513:31)
    at reconcileChildFibers2 (chunk-3IHV7RO6.js?v=82682a78:10550:43)
    at updatePortalComponent (chunk-3IHV7RO6.js?v=82682a78:15626:37)
    at beginWork (chunk-3IHV7RO6.js?v=82682a78:15941:22)
    at beginWork$1 (chunk-3IHV7RO6.js?v=82682a78:19753:22)
    at performUnitOfWork (chunk-3IHV7RO6.js?v=82682a78:19198:20)
    at workLoopSync (chunk-3IHV7RO6.js?v=82682a78:19137:13)
    at renderRootSync (chunk-3IHV7RO6.js?v=82682a78:19116:15)

The expected behavior

No error.

Impact of fix

The bug doesn't allow me from extending DecoratorNode at all.

@etrepum
Copy link
Collaborator

etrepum commented Sep 16, 2024

Hard to say without actually being able to run any of this code but I think your project might be misconfigured so it's not compiling jsx correctly for your react version. Try updating to the latest versions of react and whatever bundlers/compilers you're using. If you provide a runnable version of the broken code, e.g. on stackblitz or codesandbox, I can take a closer look.

@dnamme
Copy link
Author

dnamme commented Sep 19, 2024

Hi @etrepum, here's a copy of my code. I'm using the following lexical packages:

  • @lexical/html
  • @lexical/list
  • @lexical/react
  • lexical
  • and all other packages that I'm using for my project

As mentioned, the code doesn't work in 0.17.1 but when I downgrade to version 0.5.0, it works. Thanks!

Repo: https://github.com/dnamme/lexical-test-091924

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

No branches or pull requests

2 participants