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: Clicks on custom plugin with react component are not propagated #946

Closed
natterstefan opened this issue Nov 12, 2019 · 3 comments
Closed

Comments

@natterstefan
Copy link
Contributor

natterstefan commented Nov 12, 2019

Issue

When rendering a React component in the plugin's render method, clicks on the React element do not trigger it's onClick.

Expected outcome

I can interact with the react component properly (eg. onClick is invoked).

Example

An example codesandbox can be found here: https://codesandbox.io/s/solitary-night-96hzk?fontsize=14. After some more testing it looks like eg. onChange on input elements is not an issue: https://codesandbox.io/s/sweet-resonance-p7xwu.

The React component

import React, { useEffect, useState } from "react";
import ReactDOM from "react-dom";

export default class Custom {
  render() {
    const Button = () => {
      const [count, setCount] = useState(0);

      useEffect(() => console.log("mounting"), []);

      const onClick = e => {
        console.log("clicked"); // << is not triggered
        setCount(prevCount => prevCount + 1);
      };

      return (
        <button onClick={onClick} type="button" style={{ padding: 10 }}>
          Click me [clicked: {count} times]
        </button>
      );
    };

    const container = document.createElement("div");
    ReactDOM.render(<Button />, container);
    return container;
  }

  save(element) {
    console.log(element);
    return {
      text: element.value
    };
  }
}

Environment

  • React: "react": "16.11.0"
  • Editorjs: "@editorjs/editorjs": "2.15.1"

Related Issues/Topics

@gohabereg already posted a gif illustrating the issue:

And I created another one. As soon as you select some text, it works:

Screen Capture on 2019-11-12 at 11-21-23

@IzotovDenis
Copy link

IzotovDenis commented Nov 19, 2019

Try this

import React, { useEffect, useState, useRef } from "react";
import ReactDOM from "react-dom";

export default class Custom {
  constructor({ api }) {
    this.api = api;
  }
  render() {
    const Button = ({ api }) => {
      const [count, setCount] = useState(0);
      const buttonRef = useRef();
      useEffect(() => console.log("mounting"), []);
      useEffect(
        () =>
          api.listeners.on(
            buttonRef.current,
            "click",
            e => {
              onClick(e);
            },
            false
          ),
        []
      );

      const onClick = e => {
        console.log("clicked"); // << is triggered
        setCount(prevCount => prevCount + 1);
      };

      return (
        <button ref={buttonRef} type="button" style={{ padding: 10 }}>
          Click me [clicked: {count} times]
        </button>
      );
    };

    const container = document.createElement("div");
    ReactDOM.render(<Button api={this.api} />, container);
    return container;
  }

  save(element) {
    console.log(element);
    return {
      text: element.value
    };
  }
}

I did not find a way to call api.listeners.off in useEffect and ReactDOM.unmountComponentAtNode(container) when block delete.

@natterstefan
Copy link
Contributor Author

I forgot to say thank you @IzotovDenis, so thanks!

For anyone interested: @allankikkas came up with a better (does not use refs) solution. See #1051 (comment).

@gohabereg
Copy link
Member

Resolved by #1252

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

4 participants