【问题标题】:Reactjs - server/client checksum mismatch errorReactjs - 服务器/客户端校验和不匹配错误
【发布时间】:2015-06-24 17:06:28
【问题描述】:

我试图让 React 先在服务器上渲染一个组件,然后在客户端用一个按钮改变状态。我已经按照几个教程将组件放在服务器和客户端上的同一节点中,并使用相同的道具来做这样的事情。但是,我仍然收到无效的校验和错误消息,并且尝试单击该按钮会导致浏览器崩溃。有什么想法我哪里出错了吗?

组件:

var React = require('react')

module.exports = React.createClass({
getInitialState: function() {
    return { from: this.props.from }
},
handleClick: function(){
    this.setState({
        from: !this.state.clicked ? 'client!' : 'server!',
        clicked: !this.state.clicked
    });
},
render: function() {
    return (
        <div>
            <div>
                This is from the HelloWorld.jsx component's render function.
            </div>
            <div>
                Rendered from: {this.state.from}
            </div>
            <input type="button" value="Click Me" onClick={this.handleClick} />
        </div>
    )
}})

浏览器:

var React = require('react')
var HelloWorld = require('../Components/HelloWorld')

var helloElement = React.render(
    <HelloWorld from = "server!" />,
    document.getElementById("reactHelloContainer"))

服务器:

var React = require('react')
  , express = require('express')
  , HelloWorld = require('./Components/HelloWorld')
  , path = require('path')

var app = express()
app.use('/pages', express.static(path.join(__dirname, 'Pages')))

app.get('/', function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/html'})
    var html = React.renderToString(
            <html>
                <head>
                    <title>Hello World</title>
                </head>
                <body>
                    <div id="reactHelloContainer">
                            <HelloWorld from="server!" />
                    </div>
                </body>
                <script src="/pages/index.js"></script>
            </html>)
    res.end(html)
})

我尝试在没有 Javascript 的情况下加载页面,服务器/客户端版本似乎相同,但这是消息:

警告:React 尝试在容器中重用标记,但校验和无效。这通常意味着您正在使用服务器渲染,并且在服务器上生成的标记不是客户端所期望的。 React 注入了新的标记来补偿哪些工作,但是您已经失去了服务器渲染的许多好处。相反,请弄清楚为什么在客户端或服务器上生成的标记不同:

(客户端)eactid=".1566xf5m134">

(服务器)eactid=".1566xf5m134.1.1.0">

【问题讨论】:

    标签: reactjs


    【解决方案1】:

    服务器在getInitialState中设置的初始状态需要与浏览器中的初始状态相匹配。实现此目的的一种方法是在脚本标签中将初始道具传递给浏览器,然后从脚本的内容中获取道具。您可以使用模板传递道具。

    浏览器 HTML:

    <div id='reactHelloContainer'></div>
    <script id='hello-props'> {Your props in JSON here}   </script>
    

    浏览器js:

    var React = require('react');
    var HelloWorld = require('../Components/HelloWorld');
    
    component = React.createFactory(HelloWorld);
    var props = JSON.parse(document.getElementById("hello-props").innerHTML);
    React.render(component(props), document.getElementById('reactHelloContainer'));   
    

    【讨论】:

    • 请不要这样做
    • @AngelJosephPiscola 如果您能详细说明为什么这是一个坏主意,那将会很有帮助。我也很好奇您是否有其他设置初始状态的方法。谢谢!
    • 这似乎是常态,实际上.. 这个启动器正在做类似的事情:github.com/mhart/react-server-example。请注意他没有直接内联道具并使用 json 解析来获取它们......这似乎与 React 或 Javascriptisms 背道而驰。你最好把它们放在 window.__PREFETCHED_DATA__ 或类似的地方。
    • 然后我已经完成和玩过的服务器端渲染看起来不像你的任何一个例子,所以我可能会做一些不同的事情。不过,我还没有从头开始尝试过这样的事情,所以可能是细节只是从我的角度抽象出来的。
    • 您链接到的示例做了类似的事情;他们将 JavaScript 注入到标记中以设置包含初始状态的变量。我认为这样做没有任何内在优势。
    猜你喜欢
    • 2018-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多