【发布时间】:2016-08-06 00:28:30
【问题描述】:
更新:问题已隔离 - React 的 react-rails 和 npm 版本不同 - 在下面自己的答案中修复
在 rails 5 上使用 rails-react 并收到此警告:
Replacing React-rendered children with a new root component. If you
intended to update the children of this node, you should instead have
the existing children update their state and render the new
components instead of calling ReactDOM.render.
该网站似乎运行良好,但显然有些问题:)
index.html.erb:
<div class="item">
<%= react_component('WeatherRoot', {}, { :prerender => true } ) %>
</div>
components.js:
window.React = require('react');
window.ReactDOM = require('react-dom');
window.WeatherRoot = require('./components/containers/WeatherRoot.es6').default;
WeatherRoot.es6.js
import React, { Component } from 'react';
import { render } from 'react-dom'
import { Provider } from 'react-redux';
import WeatherContainer from './WeatherContainer.es6';
import configureStore from '../store/configureStore.es6';
import {fetchWeather} from '../actions/weather.es6';
const store = configureStore();
// Request Data as Early as Possible
store.dispatch(fetchWeather());
export default class WeatherRoot extends Component {
render() {
return (
<Provider store={store}>
<WeatherContainer />
</Provider>
);
}
}
WeatherContainer.es6
import { connect } from 'react-redux'
import Weather from '../components/Weather.es6';
export function WeatherContainerImpl(props){
return (<div>HELLO</div>);
}
const mapStateToProps = (state, ownProps) => {
return {
weather: state.weather.data
}
}
const mapDispatchToProps = (dispatch, ownProps) => {
return {
dispatch
}
}
const WeatherContainer = connect(
mapStateToProps,
mapDispatchToProps
)(WeatherContainerImpl);
export default WeatherContainer;
页面渲染:
<div data-react-class="WeatherRoot" data-react-props="{}">
<div data-reactroot="" data-reactid="1" data-react-checksum="-951512882">HELLO</div>
</div>
替换为客户端渲染:
<div data-react-class="WeatherRoot" data-react-props="{}">
<div data-reactid=".0">HELLO</div>
</div>
调试 ReactMount.js 显示此方法返回 true 作为警告的来源:
/**
* True if the supplied DOM node has a direct React-rendered child that is
* not a React root element. Useful for warning in `render`,
* `unmountComponentAtNode`, etc.
*
* @param {?DOMElement} node The candidate DOM node.
* @return {boolean} True if the DOM element contains a direct child that was
* rendered by React but is not a root element.
* @internal
*/
function hasNonRootReactChild(node) {
var reactRootID = getReactRootID(node);
return reactRootID ? reactRootID !== ReactInstanceHandles.getReactRootIDFromNodeID(reactRootID) : false;
}
从服务器端渲染和
ReactInstanceHandles.getReactRootIDFromNodeID(reactRootID)
使用此实现返回 null:
(id) {
if (id && id.charAt(0) === SEPARATOR && id.length > 1) {
var index = id.indexOf(SEPARATOR, 1);
return index > -1 ? id.substr(0, index) : id;
}
return null;
}
看起来 id 需要以 .通过?
为什么服务器端渲染的 id 不以 .? 开头?
也许我有不同版本的反应?但两者看起来都像 14.8
添加一些调试:
export function WeatherContainer(props){
console.log("WeatherContainer", React.version)
return (<div>HELLO</div>);
}
显示这些日志:
WeatherContainer 15.2.1
WeatherContainer 0.14.8
!!!!
现在如何弄清楚我是如何获得两个版本的?
【问题讨论】:
-
我刚刚阅读了整个问题,发现您有两个不同的反应版本?我会先解决这个问题,我猜 react-rails 附带一个版本,而你使用的是不同的版本。
-
是的,我花了好几个小时才弄清楚,我正在添加注释,因为抱歉会更新标题
标签: javascript ruby-on-rails reactjs redux connect