-
Notifications
You must be signed in to change notification settings - Fork 49.4k
Description
tl;dr: If you have a component that returns null
and it rerenders, the noscript tag is unmounted and a new one is created because shouldUpdateReactComponent gets <ReactEmptyComponentType />
and null
and returns false.
This came out of some internal components that were breaking after the most recent update.
I haven't gone to see if this is more widely broken - it might have been before any of the recent updates, just that the empty component is triggering it reliably. I've been some reports of <img>
having similar weird problems that we couldn't track down. It's use of LocalEventTrapMixin
is very similar to what's happening in ReactEmptyComponentType
.
The trigger here is that we're triggering an update during the mount phase. When we do this <Child key="0">
works correctly because it's before <Child key="1">
which is triggering Parent
to rerender. <Child key="2">
is the broken one because its componentDidMount
hasn't been called yet. So we actually call its componentWillUnmount
first. Then we still call its componentDidMount
.
There's also the whole question of why we're trying to unmount anything at all here. It seems like we shouldn't be doing that.
Drop this into examples/basic-jsx-harmony and debug with pausing on caught exceptions. I added some breakpoints in ReactEmptyComponent to make it super obvious.
'use strict';
var Child = React.createClass({
componentDidMount() {
this.props.onMount && this.props.onMount();
},
render() {
if (!this.props.visible) {
return null;
}
return <div>hello world</div>;
}
})
var Parent = React.createClass({
update() {
this.forceUpdate();
},
render() {
return (
<div>
<Child key="0" visible={false} />
<Child key="1" visible={true} onMount={this.update} />
<Child key="2" visible={false} />
</div>
);
}
})
React.render(
<Parent/>,
document.getElementById('container')
);