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'&lt;script type='babel' src='client_bundle.js'&gt;&lt;/script&gt; 怎么样了?为什么要输入 babel? 此外,根据您编译 javascript 的方式,您的客户端条目中可能需要 babel-polyfill

【讨论】:

您好!如果我没有将 type='babel' 放在我的 client_bundle.js 脚本上,则会导致发生引用错误。 那是因为脚本标签甚至没有加载。如果我没记错的话,错误是require not defined 或类似的东西。

以上是关于ReactDOM.hydrate() 在初始 s-s-r (React JS) 后不起作用的主要内容,如果未能解决你的问题,请参考以下文章

Parcel Bundler 和 React 服务器端渲染

初始化列表

在C ++中初始化一个指向结构的指针数组

c语言 提示 使用了未初始化的局部变量

在类内部初始化类

如何在 C++ 类中初始化二维字符指针