I recently updated react to v15.4.2, and my app doesn't work which works great in v0.14.
The problem is when I click a button (use react-router's ) jump to another page:
DOMChildrenOperations.js:65 Uncaught DOMException: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.
at removeChild (http://localhost:8083/build/main.js:15649:14)
at Object.processUpdates (http://localhost:8083/build/main.js:15793:11)
at Object.dangerouslyProcessChildrenUpdates [as processChildrenUpdates] (http://localhost:8083/build/main.js:48437:27)
at processQueue (http://localhost:8083/build/main.js:50878:29)
at ReactDOMComponent._updateChildren (http://localhost:8083/build/main.js:51096:9)
at ReactDOMComponent.updateChildren (http://localhost:8083/build/main.js:51040:12)
at ReactDOMComponent._updateDOMChildren (http://localhost:8083/build/main.js:48211:12)
at ReactDOMComponent.updateComponent (http://localhost:8083/build/main.js:48029:10)
at ReactDOMComponent.receiveComponent (http://localhost:8083/build/main.js:47991:10)
at Object.receiveComponent (http://localhost:8083/build/main.js:11340:22)
and then if I click the browser's back button:
Uncaught Error: Attempted to update component `Users` that has already been unmounted (or failed to mount).
at invariant (http://localhost:8083/build/main.js:5126:15)
at ReactCompositeComponentWrapper.updateComponent (http://localhost:8083/build/main.js:46836:31)
at ReactCompositeComponentWrapper.receiveComponent (http://localhost:8083/build/main.js:46799:10)
at Object.receiveComponent (http://localhost:8083/build/main.js:11340:22)
at Object.obj.(anonymous function) [as receiveComponent] (chrome-extension://fmkadmapgofadopljbjfkapdkoienihi/build/backend.js:8390:20)
at Object.updateChildren (http://localhost:8083/build/main.js:46166:25)
at ReactDOMComponent._reconcilerUpdateChildren (http://localhost:8083/build/main.js:50949:32)
at ReactDOMComponent._updateChildren (http://localhost:8083/build/main.js:51053:31)
at ReactDOMComponent.updateChildren (http://localhost:8083/build/main.js:51040:12)
at ReactDOMComponent._updateDOMChildren (http://localhost:8083/build/main.js:48211:12)
Here's my code:
Index.js
import 'babel-polyfill';
import 'dialog-polyfill';
import React from "react";
import {render} from "react-dom";
import {Provider} from 'react-redux';
import {createStore} from 'redux';
import configureStore from './store/configureStore';
import '../../assets/js/material.min.js';
import '../../assets/css/material.min.css';
import '../../assets/css/css-lib.css';
import '../../assets/css/style.css';
import '../../assets/css/react-datepicker.css';
import reducer from "./reducers";
import routes from "./routes";
let initialState = window.__INITIAL_STATE__;
const store = configureStore(initialState);
render(
<Provider store={store}>
{routes}
</Provider>,
document.querySelector('#root')
);
routes.js
import React from "react";
import {Router, browserHistory, Route, IndexRoute} from "react-router";
import App from '../container';
import Dashboard from '../Dashboard';
import Users from '../Users';
import Test from '../Test';
const routes = (
<Router routes={routes} history={browserHistory}>
<Route path='/' component={App}>
<IndexRoute component={Dashboard} />
<Route path='users' component={Users} />
<Route path='test' component={Test} />
</Route>
</Router>
)
export default routes;
The key is all my component is child of the container App.js. It works fine with react 0.14.
App.js
import React, {Component, Children, cloneElement} from 'react';
import {connect} from 'react-redux';
import * as actions from '../actions';
import Modal from '../components/Modal';
import WindowLoading from '../components/WindowLoading';
import style from './style.css';
class App extends Component {
constructor(props, context) {
super(props, context);
}
render() {
let props = {};
const keys = Object.keys(this.props);
keys.forEach(key => {
if(key === 'children') return;
Object.assign(props, {[key]: this.props[key]});
})
const childrenWithProps = Children.map(this.props.children,
child => cloneElement(child, props)
);
const {setModal, modal: {title, content, actions}, windowLoading} = this.props;
return (
<div id="app" className="h100">
{childrenWithProps}
<Modal
title={title}
content={content}
actions={actions}
setModal={setModal}
/>
{(windowLoading) ? <WindowLoading /> : ''}
</div>
);
}
};
function mapStateToProps(state) {
return state;
}
function mapDispatchToProps(dispatch) {
const actionNames = Object.keys(actions);
let actionProps = {dispatch};
actionNames.forEach(name => {
Object.assign(actionProps, {
[name]: (...rest) => {
dispatch(actions[name](...rest));
}
})
})
return actionProps;
}
export default connect(mapStateToProps, mapDispatchToProps)(App);
I tried to put the child components (Dashboard, users and test) out side the container, no error.
This usually means somewhere you're swallowing an exception coming from your own code.
See https://github.com/facebook/react/issues/6895#issuecomment-281405036.
If you can reproduce this reliably and you're sure you're not swallowing any exceptions, please create a minimal project demonstrating the problem. Just posting snippets of code here isn't very helpful unfortunately.
Thanks!
Going to close because we've had tens of issues like this, and they always were due to swallowed exceptions. Happy to reopen if you provide a reproducing case that doesn't swallow errors.
@gaearon what it means by swallowed exceptions ??
Have you had a chance to read the link I posted earlier? https://github.com/facebook/react/issues/6895#issuecomment-281405036
Thanks , i have read it ,
I am also facing the same issue, i will try to explain
I have a component with this render method.
```
render () {
let render: JSX.Element;
let remoteId = "r_" + this.props.thread.get('uid');
render =
I have a event `videoadded` .This event adds the `<video autoplay="" id="1_video_incoming"></video>`
in the `peerVideo` class.
Like this
this.webrtc.on('videoAdded', function (video: any, peer: any) {
let remotes = document.getElementById('r_' + peer.id);
if (remotes) {
remotes.appendChild(video);
}
})
Normally when i want to remove the video i call function
let removeChild = function (peer) {
var container = document.getElementById('r_' + peer.id);
var videoEl = peer.videoEl; //it got video element
if (container && videoEl) {
container.removeChild(videoEl); // my code is breaking here
}
};
``
Normally it behaves correctly, but in case of reconnecting , i have to fire
videoAddedevent again. It adds the
It throws error
Uncaught DOMException: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.
My guess would be when i try to update the div again . <div className="peerVideo" id={remoteId}></div>
does not detect that it has child anymore. may be because react behaviour or something i am doing wrong.
I tried this method also https://github.com/u-wave/troybetz-react-youtube/commit/6b4c98aba5059dffca90d595054d77028ee841a2 . but it is also not working.
This is not the intended way to use React. React doesn鈥檛 like when you鈥檙e trying to do DOM mutations by hand because it later tries to reconcile the DOM, and repeats what you鈥檝e already done, causing failures.
Instead, you should let React take care of updating the DOM. For example, instead of calling appendChild
or removeChild
, you would call setState()
, and in your render function you would either return the element or not depending on the current state:
render () {
let remoteId = "r_" + this.props.thread.get('uid');
let video = this.state.showVideo ?
<div className="peerVideo" id={remoteId}></div> :
null;
return (
<div >{video}</div>
)
}
This is described in Conditional Rendering in the docs.
Got it. That remove function was in 3rd party library which was causing the problem. but they do provide config to override that function.
Thank you :)
Glad I could help!
@gaearon I've got this problem with draft-js, would you help to fixed it https://github.com/facebook/draft-js/issues/1320 ?
@gaearon I think I'm seeing the Failed to execute 'removeChild'
error because I was testing error boundaries with a component that throws only when rendered on the client, so it was throwing the error during hydration...are error boundaries intended to work during hydration? When I made the test component throw after hydration, the error boundary worked as desired.
It looks like this error can be caused by a number of things, but I'm posting what fixed mine in case anyone has the same situation.
I was rendering one of two <i>
tags with different key
properties based on a ternary like so:
{
myBoolean
? <i key="icon-check" className="fas fa-check fa-stack-1x has-text-link" />
: <i key="icon-arrow" className="fas fa-arrow-right fa-stack-1x has-text-link" />
}
I fixed the error by wrapping each <i>
tag with a <div>
and moving the keys to the divs:
{
myBoolean
? <div key="icon-check" style={{ display: "inline" }}><i className="fas fa-check fa-stack-1x has-text-link" /></div>
: <div key="icon-arrow" style={{ display: "inline" }}><i className="fas fa-arrow-right fa-stack-1x has-text-link" /></div>
}
Hope this helps!
Most helpful comment
This is not the intended way to use React. React doesn鈥檛 like when you鈥檙e trying to do DOM mutations by hand because it later tries to reconcile the DOM, and repeats what you鈥檝e already done, causing failures.
Instead, you should let React take care of updating the DOM. For example, instead of calling
appendChild
orremoveChild
, you would callsetState()
, and in your render function you would either return the element or not depending on the current state:This is described in Conditional Rendering in the docs.