17

I am trying to use MDL on an existing project that uses React, and I am running into several issues. Things seem fine on the first load, although there are many warning messages:

Warning: ReactMount: Root element has been removed from its original container. New container:

This happens pretty much for every DOM element that has a class recognized by MDL (examples: mdl-layout, mdl-layout__content, etc.) and it happens on any DOM changes.

Further, when changing routes, there is an "Invariation Violation" error:

Uncaught Error: Invariant Violation: findComponentRoot(..., .0.2.0.1.1.0.0.0.0): Unable to find element. This probably means the DOM was unexpectedly mutated (e.g., by the browser)...

Does this mean that MDL and React are pretty much incompatible?

Update: The issue disappears if the element with class="mdl-js-layout" is not the topmost element in the reactjs render function. Once I wrapped that element, all is good.

Penar
  • 591
  • 5
  • 10
  • 1
    My project uses React and MDL just fine. They definitely are not incompatible – Michael Parker Aug 13 '15 at 22:33
  • 1
    Thanks @MichaelParker it's good to know the two work well together. – Penar Aug 14 '15 at 02:11
  • 1
    Just saw your update. Could you elaborate a bit more on what you had to do to fix this? I'm still curious as to what may have caused your issue. – Michael Parker Aug 14 '15 at 13:51
  • 2
    I added a parent div to the app's render function. What caused my issue was the fat that the element with class "mdl-ja-layout" was the root of React's render. MDL likes to make changes to the DOM, and React did not like that change happening to the root element. I'm not sure why, but adding a different element as parent, an element without a mdl-js-* class, fixed the issue. – Penar Aug 15 '15 at 18:36

2 Answers2

9

Try to wrap a DIV element outside, I just fixed that problem in this way.

If you are using Redux + React + MDL + React-Router, You can wrap a DIV element to Provider element:

import React, { createStore }      from 'react';
import { Provider }                from 'react-redux';
import Router, { HistoryLocation } from 'react-router';

var store = createStore();

Router.run(routes, HistoryLocation, (Handler, state) => {
    React.render((
        <div>
            <Provider store={store}>
            {
                () => <Handler {...state} />
            }
            </Provider>
        </div>
    ), document.body);
});

Hope it can help you :)

Brothers
  • 91
  • 3
  • 1
    That worked from me also with a slightly different router setup ``` Router.run(routes, Router.HistoryLocation, (Root, state) => { React.render((
    ), document.body ); }); ```
    – ActualAl Oct 20 '15 at 08:55
6

The first and second errors are related to each other, take a look at MDL's layout source code. I would say that the following causes the mutation of your React root element (which is the mdl-js-layout component):

var container = document.createElement('div');
container.classList.add(this.CssClasses_.CONTAINER);
this.element_.parentElement.insertBefore(container, this.element_);
this.element_.parentElement.removeChild(this.element_);
container.appendChild(this.element_);

If you take a look at the official example, you can see that MDL massively changes your markup and that is exactly what React doesn't like.


BTW: I also have composed an article which studies the combination of React with MDL.
Yan Foto
  • 10,850
  • 6
  • 57
  • 88
  • 1
    the blog link is broken, please include relevant information not just link to it – daw Oct 06 '15 at 14:21
  • 1
    @daw the relevant info is given, the in-depth info is linked. If the blog is out of reach, you can just wait until its up and running again. – Yan Foto Oct 06 '15 at 14:26