ReactDOM.hydrate() 在初始 s-s-r (React JS) 后不起作用
Posted
技术标签:
【中文标题】ReactDOM.hydrate() 在初始 s-s-r (React JS) 后不起作用【英文标题】:ReactDOM.hydrate() not working after initial s-s-r (React JS) 【发布时间】:2019-03-19 12:05:16 【问题描述】:在应用程序的初始服务器端呈现之后,我的 onClick 事件(在我的 Homepage.js 组件中的按钮上)没有执行。看来我的 client.js 文件中的 ReactDom.hydrate() 不起作用。任何帮助将不胜感激!您可以访问以下 repo 获取整个代码库 https://github.com/thegreekjester/React_s-s-r。
运行和重现问题的步骤:
npm 安装 npm 运行开发 在浏览器中打开localhost:3000
点击出现的按钮
您应该在控制台中看到一些消息,但您没有看到
主页.js:
import React from 'react'
import connect from 'react-redux'
class HomePage extends React.Component
exampleMethod()
console.log('Shit is going down')
render()
return(
<div>
<h1>this.props.state.attributes.name</h1>
<button onClick=() => this.exampleMethod()> Console log some text </button>
</div>
)
const mapStateToProps = (state) => (state:state.optimizelyReducer);
const mapDispatchToProps = (dispatch) => (
dataFileManager: (timing, id, attributes) => dispatch(type:'USER_SERVICE', id:id, attributes:attributes,
dispatch(type:'DATAFILE_MANAGER', timing:timing)),
updateAttr: (attr) => dispatch(type:'UPDATE_ATTR', attr:attr, value:value)
);
HomePage = connect(mapStateToProps, mapDispatchToProps)(HomePage);
export default HomePage;
client.js:
import React from 'react';
import ReactDOM from 'react-dom';
import BrowserRouter from 'react-router-dom';
import Provider as ReduxProvider from 'react-redux'
import App from './App.js'
import configureStore from './store/configureStore';
const preloadedState = window.__PRELOADED_STATE__
const store = configureStore(window.__PRELOADED_STATE__);
ReactDOM.hydrate(
<ReduxProvider store=store>
<BrowserRouter>
<App />
</BrowserRouter>
</ReduxProvider>,
document.getElementById('root')
);
server.js:
import 'babel-polyfill'
import express from 'express';
import React from 'react';
import ReactDOMServer from 'react-dom/server';
import StaticRouter from 'react-router'
import bodyparser from 'body-parser'
import App from './src/App.js'
import createStore from 'redux'
import Provider from 'react-redux'
import configureStore from './src/store/configureStore.js'
const app = express();
const PORT = process.env.PORT || 3000
app.use(bodyparser.json());
app.use(express.static('build/public'));
function handleRender(req, res)
const store = configureStore()
const context =
const html = ReactDOMServer.renderToString(
<Provider store=store>
<StaticRouter location=req.url context=context>
<App/>
</StaticRouter>
</Provider>
)
const preloadedState = store.getState()
res.send(renderFullPage(html, preloadedState))
function renderFullPage(html, preloadedState)
return `
<html>
<head>
</head>
<body>
<div id='root'>$html</div>
<script>window.__PRELOADED_STATE__ = $JSON.stringify(preloadedState)</script>
<script type='babel' src='client_bundle.js'></script>
</body>
</html>`
app.use(handleRender)
app.listen(PORT, () =>
console.log(`React s-s-r App is running on port $PORT`)
);
Webpack.client.js
const path = require('path');
const webpackNodeExternals = require('webpack-node-externals');
module.exports =
// production || development
mode: 'development',
// Inform webpack that we're building a bundle
// for nodeJS, rather then for the browser
target: 'node',
// Tell webpack the root file of our
// server application
entry: './src/client.js',
// Tell webpack where to put the output file
// that is generated
output:
filename: 'client_bundle.js',
path: path.resolve(__dirname, 'build/public'),
publicPath: '/build/public'
,
module:
rules: [
test: /\.js?$/,
loader: 'babel-loader',
exclude: '/node_modules/',
options:
presets: [
'react', 'stage-0', ['env',
target: 'web'
]
]
]
;
Webpack.server.js
const path = require('path');
const webpackNodeExternals = require('webpack-node-externals');
module.exports =
// production || development
mode: 'development',
// Inform webpack that we're building a bundle
// for nodeJS, rather then for the browser
target: 'node',
// Tell webpack the root file of our
// server application
entry: './server.js',
// Tell webpack where to put the output file
// that is generated
output:
filename: 'bundle.js',
path: path.resolve(__dirname, 'build'),
publicPath: '/build'
,
module:
rules: [
test: /\.js?$/,
loader: 'babel-loader',
exclude: '/node_modules/',
options:
presets: [
'react', 'stage-0', ['env',
target: browsers: ['last 2 versions']
]
]
]
,
// Tell webpack not to bundle any libraries that exist in the 'node_modules' folder
// into the server bundle
externals: [webpackNodeExternals()]
;
【问题讨论】:
【参考方案1】:有几点你必须检查:
为什么在客户端 webpack 配置中使用target: 'node'
?
<script type='babel' src='client_bundle.js'></script>
怎么样了?为什么要输入 babel?
此外,根据您编译 javascript 的方式,您的客户端条目中可能需要 babel-polyfill
。
【讨论】:
您好!如果我没有将 type='babel' 放在我的 client_bundle.js 脚本上,则会导致发生引用错误。 那是因为脚本标签甚至没有加载。如果我没记错的话,错误是require not defined
或类似的东西。以上是关于ReactDOM.hydrate() 在初始 s-s-r (React JS) 后不起作用的主要内容,如果未能解决你的问题,请参考以下文章