ReactJs: Adding an element to the DOM tree

How can you add an item directly to the main DOM? Using Editor.js, I created a custom block. However, the custom block is created on a seperate DOM tree which makes it inaccessible with Redux.

This is a screenshot of the DOM tree: https://snipboard.io/vrbZLt.jpg

Index.js where the main DOM is rendered:

ReactDOM.render(
  <React.StrictMode>
    <Provider store={store}>
      <App />
    </Provider>
  </React.StrictMode>,
  document.getElementById('root')
);

This is where the custom block was created:

export default class Checklist {
  static get toolbox() {
    return {
      icon: 'SVG Code...'
      title: 'Checklist',
    };
  }

  static get isReadOnlySupported() {
    return true;
  }

  constructor({ data, config, api, readOnly }) {
    this.api = api;
    this.readOnly = readOnly;
    this.data = {
      events: data.events || [],
    };

    this.CSS = {
      wrapper: 'walkthrough-timeline',
    };

    this.nodes = {
      holder: null,
    };
  }

  render() {
    const rootNode = document.createElement("div");
    rootNode.setAttribute("class", this.CSS.wrapper);
    this.nodes.holder = rootNode;

    const onDataChange = (newData) => {
      this.data = {
        ...newData,
      };
    };

    ReactDOM.render(
      <ChecklistTool
        onDataChange={onDataChange}
        readOnly={this.readOnly}
        data={this.data}
        isAdmin={true}
      />,
      rootNode
    );

    return this.nodes.holder;
  }

  save() {
    return this.data;
  }
}

I realize that document.createElement("div") will create a new DOM. I’m just not sure how to create the ChecklistTool component inside of the main DOM so it gets access to Redux. Any ideas on how to make this happen? Thank you!

Answer

Two things might put you in the right direction.

Ref

The way to access the existing DOM tree is through a ref.

  const ref = useRef()
  return <div ref={ref}>Hello</div>

You can apply all your DOM method via ref.current

Render

Render function is called every time, this is not good, because you don’t want to handle the DOM in every render. Instead you have to look for some startup or cleanup location. Use function component as a example.

  useEffect(() => {
    ref.current && ref.current.textContent = "Hello World"
    return () => {
       ref.current.textContent = "Notitle"
    }
  }, [])

The above will set the title once after the component mount and set the title back after unmount.

Based on the above two points, you can give it shot for your own logic.