Tiptap Events don't work when attached to an editor that is passed down to components via props

516 views Asked by At

I've created an editor using useEditor. I want to bind events to it, to get active state of a specific mark and getAttributes to get link hrefs to update urls of previously set links. I cannot bind those events in components where i'm receiving that editor through props.

File : Editor.jsx


var editor = useEditor({
    extensions: EditorExtensions,
    onUpdate({ editor }) {
      setState({
        ...state,
        json: editor.getJSON(),
        html: editor.getHTML(),
        editorTextContent: editor.state.doc.textContent,
      });
    },
  });

// passing this editor instance to toolbar down in big component
<Toolbar editor={editor} /> // relevnat part

Toolbar.jsx

const Toolbar = ({ editor }) => {
  return (
    <div className="">
      <Btns.UndoBtn editor={editor} />
      <Btns.RedoBtn editor={editor} />
      <Btns.VerticalDivider />
      <Btns.BoldBtn editor={editor} />
      <Btns.ItalicBtn editor={editor} />
      <Btns.UnderlineBtn editor={editor} />
      <Btns.VerticalDivider />
    </div>

ToolbarButtons.jsx


export const BoldBtn = ({ editor }) => {
  const onClick = () => editor.chain().focus().toggleBold().run();
  return (
    <IcnBtn shortcut={"Ctrl + B"} Icon={Icons.BoldIcon} onClick={onClick} />
  );
};

Here in toolbar buttons, I've created different buttons that accept an editor. I use this editor to update editor state, format text etc. This BoldBtn is an example where i'm using editor to make text bold, it works perfectly. The problem I have exists in all other components and every component receive an editor so they are similar.

This is the problem BoldBtn

export const BoldBtn = ({ editor }) => {
  var [boldState, setBoldState] = useState(false);
  editor.on("update", ({ editor }) => {});
  editor.on("selectionUpdate", ({ editor }) => {
    var boldIsActive = editor.isActive("bold");
    setBoldState(boldIsActive);
  });

  const onClick = () => editor.chain().focus().toggleBold().run();
  return (
    <IcnBtn isActive={boldState} shortcut={"Ctrl + B"} Icon={Icons.BoldIcon} onClick={onClick} />
  );
};

Editor instance inside onClick works perfectly> editor.chain().focus().toggleBold().run().

These editor.on() events don't work and give these errors

1 Cannot read properties of null (reading 'isActive')

2 TypeError: Cannot read properties of null (reading 'on')

Somehow they are null when they are accessed inside component, and work as they should inside functions. I might be making a very basic mistake, I'm a mobile app developer, Please suggest any solution or work around for this. Thank you.

1

There are 1 answers

0
samadfullstack On BEST ANSWER

use useEffect hook, pass editor as a dependency, inside useEffect you can attach events.


    export const BoldBtn = ({ editor }) => {
      var [state, setState] = useState();
      useEffect(() => {
        if (!editor) {
          console.log("No Editor");
          return;
        }
        editor.on("update", ({ editor }) => {
          var boldIsActive = editor.isActive("bold");
          setState(boldIsActive);
          console.log("boldstate", state);
        });
      }, [editor]);
    
      const onClick = () => editor.chain().focus().toggleBold().run();
      return (
        <IcnBtn
          active={state}
          shortcut={"Ctrl + B"}
          Icon={Icons.BoldIcon}
          onClick={onClick}
        />
      );
    };