更新:問題隔離 - React的react-rails和npm版本不同 - 修復自己的答案Rails 5 Redux React服務器端渲染爲客戶端提供了JavaScript警告'用一個新的替換React渲染的子...'
使用在軌道上軌5 - 反應,得到這樣的警告:
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;
}
基本上節點的「1」的一個id服務器端渲染和
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需要以a開頭。通過?
爲什麼服務器端不能以a開頭?
也許我有不同版本的反應?但兩者看起來像14.8
添加一些調試:
export function WeatherContainer(props){
console.log("WeatherContainer", React.version)
return (<div>HELLO</div>);
}
顯示這些日誌:
WeatherContainer 15.2.1
WeatherContainer 0.14.8
!!!!
現在如何弄清我如何得到兩個版本?
我剛纔讀的整個問題,找出你有兩個不同版本的反應?我會首先解決這個問題,我猜測反應軌道是與一個版本一起發貨的,而你正在使用另一個版本。 –
是啊,花了我幾個小時才弄明白,我在添加筆記,因爲我去對不起會更新標題 – stujo