vis-timeline icon indicating copy to clipboard operation
vis-timeline copied to clipboard

Memory leak when using JSX in templates

Open Matthijs-Brouwer opened this issue 2 years ago • 1 comments

Hi,

I am using the vis-js timeline library and I would like to use JSX in the template option as shown in the example. I use a combination of ReactDOM.createPortal and ReactDOM.render to create a template for all my items.

const options = {
  template: (item, element) => {
    return ReactDOM.createPortal(
      ReactDOM.render(<Tag key={item.id}>item.id</Tag>, element),
      element
    );
  },
};

This seems to be causing a memory leak. Over time the number of Detached HTMLDivElements grows until I run out of memory.
When I change the code to regular javascript the memory usage seems fine.

const options = {
  template: (item, element) => {
    return "<div key={item.id}>item.id</div>";
  },
};

As I understand from this page I should not be using the ReactDOM.CreatePortal in this case because the Timeline and the items in it are children of my own DOM node. But when I leave it out I get the same error as reported here. I am curious what causes this memory leak and how I could avoid it. Especially since the combination of ReactDOM.CreatePortal and ReactDOM.Render are used in the previously mentioned example.

Matthijs-Brouwer avatar Aug 20 '21 08:08 Matthijs-Brouwer

Would it be possible that the cause is that you are not destroying the template when required?

Fanna1119 avatar Nov 30 '21 19:11 Fanna1119

This looks like a react issue to me.

mojoaxel avatar Sep 02 '23 20:09 mojoaxel

This issue is from 2 years ago, I Think it should be fine to close it.

Matthijs-Brouwer avatar Sep 04 '23 06:09 Matthijs-Brouwer

This issue is still present. I would expect this to work if you guys mention in your documentation that React templates are supported.

Edit:

After messing around with my code, I've found a way which makes it work with react 17.0.2

template: function (item, element, data) {
	if(!item) return

	// instead of using 
	// return ReactDOM.render(...)
	// use the following
	// i.e. return undefined

	ReactDOM.render(...)
}

I'm not sure what happens internally as a result of using this pattern so I'd appreciate if someone can provide some insight, thank you!

bh0mbalziyad avatar Mar 15 '24 04:03 bh0mbalziyad