Brent Traut Brent Traut - 1 year ago 91
React JSX Question

How to avoid memory leaks from jQuery?

jQuery holds references to DOM nodes in its internal cache until I explicitly call $.remove(). If I use a framework such as React which removes DOM nodes on its own (using native DOM element APIs), how do I clean up jQuery's mem cache?

I'm designing a fairly large app using React. For those unfamiliar, React will tear down the DOM and rebuild as needed based on its own "shadow" DOM representation. The part works great with no memory leaks.

Flash forward, we decided to use a jQuery plugin. After React runs through its render loop and builds the DOM, we initialize the plugin which causes jQuery to hold a reference to the corresponding DOM nodes. Later, the user changes tabs on the page and React removes those DOM elements. Unfortunately, because React doesn't use jQuery's $.remove() method, jQuery maintains the reference to those DOM elements and the garbage collector never clears them.

Is there a way I can tell jQuery to flush its cache, or better yet, to not cache at all? I would love to still be able to leverage jQuery for its plugins and cross-browser goodness.

Answer Source

If your plugin exposes a method to programatically destroy one of its instances (i.e. $(element).plugin('destroy')), you should be calling that in the componentWillUnmount lifecycle of your component.

componentWillUnmount is called right before your component is unmounted from the DOM, it's the right place to clean up all external references / event listeners / dom elements your component might have created during its lifetime.

var MyComponent = React.createClass({
    componentDidMount() {
    componentWillUnmount() {
    render() {
        return <div ref="jqueryPluginContainer" />;

If your plugin doesn't expose a way to clean up after itself, this article lists a few ways in which you can try to dereference a poorly thought out plugin.

However, if you are creating DOM elements with jQuery from within your React component, then you are doing something seriously wrong: you should almost never need jQuery when working with React, since it already abstracts away all the pain points of working with the DOM.

I'd also be wary of using refs. There are only few use cases where refs are really needed, and those usually involve integration with third-party libraries that manipulate/read from the DOM.

If your component conditionally renders the element affected by your jQuery plugin, you can use callback refs to listen to its mount/unmount events.

The previous code would become:

var MyComponent = React.createClass({
    handlePluginContainerLifecycle(component) {
        if (component) {
            // plugin container mounted
            this.pluginContainerNode = React.findDOMNode(component);
        } else {
            // plugin container unmounted
    render() {
        return (
                {Math.random() > 0.5 &&
                    // conditionally render the element
                    <div ref={this.handlePluginContainerLifecycle} />