Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # 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

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants