很抱歉打扰您以检查我的问题,我已经在stackoverflow中自动搜索了我的问题,并在之前阅读了此内容:same question as mine
它提到了解决此警告的这种方式,但我认为这不是解决该问题的真正好方法: suppressHydrationWarning = {true} prop也可以在渲染的元素上使用。但是,从文档的角度看,该道具必须很少使用。更好的解决方案是适当地使用hydrate()或render()。
所以,这是我使用React SSR时遇到的麻烦:
这是我的特殊代码[fake]:
// app.js
const http = require('http')
const fs = require('fs')
const path = require('path')
const demo = require('./demo')
const clientScripts = demo('Client')
let scriptsTag = ''
clientScripts.map((script) => {
scriptsTag += `<script src=${script}></script>`
})
const server = http.createServer((req, res) => {
res.setHeader("Access-Control-Allow-Origin","*");
res.setHeader("Access-Control-Allow-Headers","*");
// ssr
const ssrObj = require('./static/entry/serverEntry')
const dom = ssrObj.inital('server').dom
const store = ssrObj.inital('server').store
// const title = ssrObj.inital('server').title
console.log('in: ', dom)
res.setHeader("Content-Type","text/html;charset=utf-8");
res.end(`
<html>
<head>
<title>React & React Router4 SSR</title>
</head>
<body>
<!-- server side -->
<div id="root">${dom}</div>
<script>window.__PRELOADED_STATE__ = ${JSON.stringify(store)}</script>
<!-- ok with client side -->
${scriptsTag}
</body>
</html>
`);
});
server.listen(1234, () => {
console.log('开始监听1234端口')
})
// demo.js
const path = require('path')
const fs = require('fs')
let targetFile = ''
// suppose webpack configuration are ok, its' server output set in '/dist'
const fileList = fs.readdirSync(path.resolve(__dirname, '../dist'))
const container = []
module.exports = (params) => {
fileList.map((file) => {
const ext = path.extname(file).slice(1)
if (ext === 'js') {
const reg = new RegExp(`${params}`,"gim");
if (reg.test(file)) {
container.push(file)
}
}
})
return container
}
// /entry/serverEntry.js
require('babel-polyfill')
require('babel-register')({
presets: [ 'env' ]
})
const App = require('../common/initalEntry')
module.exports = App
// /entry/client.js
require('babel-polyfill')
require('babel-register')({
presets: [ 'env' ]
})
const App = require('../common/initalEntry')
App.inital('client').dom
// /common/initalEntry.js
import React from 'react';
// dom
import {hydrate} from 'react-dom' // client side use hydrate to replace render in react16
import {renderToString} from 'react-dom/server'
// router
import {StaticRouter, BrowserRouter} from 'react-router-dom'
// store
import { createStore } from 'redux'
import { Provider } from 'react-redux'
import * as reducers from '../store/reducers'
import { App } from './App'
export function inital (url = '') {
if (url === 'server') {
console.log(1, url)
const serverStore = createStore(reducers.counter)
return {
dom: renderToString(
<Provider store={serverStore}>
<StaticRouter location={url} context={{}}>
<App type={url} />
</StaticRouter>
</Provider>
),
store: serverStore
}
} else if (url === 'client') {
console.log(2, url, App)
const clientStore = createStore(reducers.counter, window.__PRELOADED_STATE__)
delete window.__PRELOADED_STATE__
return {
dom: hydrate(
<Provider store={clientStore}>
<BrowserRouter>
<App type={url} />
</BrowserRouter>
</Provider>
, document.getElementById('root')
),
store: clientStore
}
}
}
import React from 'react';
import {Route, Link} from 'react-router-dom'
class Text1 extends React.Component {
constructor (props) {
super(props)
}
render () {
return (
<div>i am text1.</div>
)
}
}
class Text2 extends React.Component {
render () {
return (
<div>i am text2.</div>
)
}
}
export class App extends React.Component {
constructor (props) {
super(props)
}
componentDidMount () {
console.log(this.props, '<<<<<<<')
}
goTo () {
}
render () {
return (
<div>
<Link to="/text1">go text1</Link>
<Link to="/text2">go text2</Link>
<Route path="/text1" component={Text1}></Route>
<Route path="/text2" component={Text2}></Route>
</div>
)
}
}
首先,这些是我对导致此问题的react ssr的配置。感谢查看我的问题,请给我一些处理此问题的想法。我将非常感谢您的帮助。
这是我的完整代码:just viewing and running the server/ directory is ok
再次感谢您的帮助。
我删除了App.js中的代码,然后不再显示警告,这是我的修改:
import React from 'react';
import {Route, Link} from 'react-router-dom'
export class App extends React.Component {
constructor (props) {
super(props)
}
goTo () {
console.log('click me')
}
render () {
return (
<div>
<p onClick={this.goTo.bind(this)}>123</p>
</div>
)
}
}
答案 0 :(得分:0)
// I finally solve this problem when I find something a litte bit strange in /common/initalEntry.js
import React from 'react';
// dom
import {hydrate, render} from 'react-dom'
import {renderToString} from 'react-dom/server'
// router
import {StaticRouter, BrowserRouter} from 'react-router-dom'
// store
import { createStore } from 'redux'
import { Provider } from 'react-redux'
import * as reducers from '../store/reducers'
import { App } from './App'
export function inital (type, url = '') {
if (type === 'server') {
const serverStore = createStore(reducers.counter)
return {
dom: renderToString(
<Provider store={serverStore}>
{/* What I pass in location is a empty value which calls 'url' which causes me a lot of time to figure out what happened.The right way is pass the request url received by node.js server to 'location', then no more warning */}
<StaticRouter location={url} context={{}}>
<App />
</StaticRouter>
</Provider>
),
store: serverStore
}
} else if (type === 'client') {
// ...ignore
}
}