React: Re-render element in componentDidMount at once Error:Cannot read property 'rootID' of null.

Created on 10 May 2016  ·  3Comments  ·  Source: facebook/react

I do ReactDOM.render #container element(top-level) in componentDidMount function, React show me some error, Cannot read property 'rootID' of null.
If I use setTimeout run ReactDOM.render, it's work. (Even after 0ms)
I feel uncertain, could someone help me?

html:

<!DOCTYPE html>
<html>
<head>
    <title>React</title>
</head>
<body>
    <div id="container"></div>
    <script type="text/javascript" src="script/lib/react.js"></script>
    <script type="text/javascript" src="script/lib/react-dom.js"></script>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
    <script type="text/javascript" src="script/bundle.js"></script>
</body>
</html>

A.jsx & B.jsx :

var A = React.createClass({
    componentDidMount: function(){
        ReactDOM.render(
            <B />,
            document.getElementById('container')
        );
    },
    render: function(){
        return (
            <div>Hello World, I'm A.</div>
        )
    }
});

var B = React.createClass({
    render: function(){
        return (
            <div>Hello World, I'm B.</div>
        )
    }
});

app.jsx:

ReactDOM.render(
    <A />,
    document.getElementById('container')
);

Most helpful comment

The real question is why are you calling ReactDOM.render from within a lifecycle method? You're trying to mount a new component at the node that the current component is mounted at, which seems like an anti-pattern.

You should use a root parent component to manage which component renders, instead of trying to re-mount at the root. If you absolutely have to have multiple React roots (which you should have a really good reason for) you should be using some sort of helper system manage this:

https://facebook.github.io/react/blog/2015/10/01/react-render-and-top-level-api.html#helpers

f you have multiple React roots, or a single root that gets deleted over time, we recommend that you always create your own wrapper API. These will all look slightly different depending on what your outer system looks like. For example, at Facebook we have a system that automatically ties into our page transition router to automatically call unmountComponentAtNode.

Rather than calling ReactDOM.render() directly everywhere, consider writing/using a library that will manage mounting and unmounting within your application.

All 3 comments

Can you reproduce your issue in a jsfiddle? https://jsfiddle.net/L3zn8dws/

The real question is why are you calling ReactDOM.render from within a lifecycle method? You're trying to mount a new component at the node that the current component is mounted at, which seems like an anti-pattern.

You should use a root parent component to manage which component renders, instead of trying to re-mount at the root. If you absolutely have to have multiple React roots (which you should have a really good reason for) you should be using some sort of helper system manage this:

https://facebook.github.io/react/blog/2015/10/01/react-render-and-top-level-api.html#helpers

f you have multiple React roots, or a single root that gets deleted over time, we recommend that you always create your own wrapper API. These will all look slightly different depending on what your outer system looks like. For example, at Facebook we have a system that automatically ties into our page transition router to automatically call unmountComponentAtNode.

Rather than calling ReactDOM.render() directly everywhere, consider writing/using a library that will manage mounting and unmounting within your application.

This seems like an unsupported pattern: you are trying to render something into a container that already contains another component whose lifecycles are currently being executed.

If you want B to appear, include <B /> from A's render output.

Was this page helpful?
0 / 5 - 0 ratings