服务器端渲染生成与客户端渲染不同的标记

时间:2016-04-28 21:10:44

标签: javascript reactjs react-router

我正在使用expressreact-router进行服务器端渲染:

这是我在服务器端的代码:

app.use(
    express.static(
        path.join(__dirname,'public')
    )
);

app.set('view engine','ejs');

app.get('*',function(req,res){
   debugger;
   match({
       routes:routes,
       location:req.url,

   },(err,redirect,props) => {
       debugger;
       if(err)
       {
           res.status(500).send(err.message);
       }
       else if(redirect)
       {
           res.redirect(redirect.pathname + redirect.search);
       }
       else if(props)
       {
           const markup = renderToString(<RouterContext {...props}/>);
           debugger;
           res.render('index',{markup});
       }
   });
});

这些是我的routes

const routes = (<Route path="/" component={App}>
            <IndexRoute component={Home}/>
            <Route path="/repos" component={Repos}>
                <Route path="/repos/:username/:reponame" component={Repo}/>
            </Route>
            <Route path="/about" component={About}/>
        </Route>);

这是我的Repos组件:

const Repos = ({children,},context) => {


    const handleSubmit = (event) => {
        event.preventDefault();
        const username=event.target.elements[0].value;
        const repo = event.target.elements[1].value;
        const path = `/repos/${ username }/${ repo }`;
        event.target.elements[0].value='';
        event.target.elements[1].value='';
        context.router.push(path);
        console.log(path);
    }

    return (<div>
        <ul>
            <li><NavLink to="/repos/reactjs/react">React</NavLink></li>
            <li><NavLink to="/repos/reactjs/react-router">React Router</NavLink></li>
            <li>
                <form onSubmit={handleSubmit}>
                    <input type="text" placeholder="userName"/>{' '}
                    <input type="text" placeholder="repo"/>{' '}
                    <button type="submit">Go</button>
                </form>
            </li>
        </ul> 
        {children}
    </div>)
};

Repos.contextTypes = {
    router: React.PropTypes.object
};

当我呈现repos路由时,我发现在呈现input元素时会发生此错误:

bundle.js:1658 Warning: React attempted to reuse markup in a container but the checksum was invalid. This generally means that you are using server rendering and the markup generated on the server was not what the client was expecting. React injected new markup to compensate which works but you have lost many of the benefits of server rendering. Instead, figure out why the markup being generated is different on the client or server:
 (client)  data-reactid="10"><li data-reactid="11"
 (server)  data-reactid="10"><ul data-reactid="11"warning @ bundle.js:1658_mountImageIntoNode @ bundle.js:20285ReactMount__mountImageIntoNode @ bundle.js:7742mountComponentIntoNode @ bundle.js:19941perform @ bundle.js:8231batchedMountComponentIntoNode @ bundle.js:19955perform @ bundle.js:8231batchedUpdates @ bundle.js:16495batchedUpdates @ bundle.js:7389_renderNewRootComponent @ bundle.js:20108ReactMount__renderNewRootComponent @ bundle.js:7742_renderSubtreeIntoContainer @ bundle.js:20185render @ bundle.js:20205React_render @ bundle.js:7742(anonymous function) @ bundle.js:649__webpack_require__ @ bundle.js:556(anonymous function) @ bundle.js:579(anonymous function) @ bundle.js:582

1 个答案:

答案 0 :(得分:0)

您的帖子中没有足够的信息让我知道到底出了什么问题。

但我发现有助于调试这是客户端中的一些简单的console.log语句。只要您的客户端引导代码调用ReactDOM.render(),请执行以下操作:

const root = document.getElementById("root");

// add these console.log lines
console.log("before");
console.log(root.innerHTML);

ReactDOM.render(<...whatever.../>, root);

// add these console.log lines
console.log("after");
console.log(root.innerHTML);

现在你可以将这两行html复制到差异工具或文本编辑器中,看看它们的不同之处。

通常的区别在于服务器呈现的状态与客户端不同。

相关问题