如何为React服务器端呈现

时间:2016-11-20 16:56:32

标签: node.js reactjs server-rendering react-server

与客户端渲染相比,我更喜欢将服务器端渲染用于几乎没有用户交互的应用程序。而webpack是编译服务器端代码的选择。

有一种情况我希望在呈现组件后更新表格 marginTop 。如果是客户端呈现,则实现将如下列出

componentDidMount() {
  const node = ReactDOM.findDOMNode(this.refs.table);
  node.style.marginTop = `-${height}`;
}

但是,在ssr上,在渲染组件时永远不会调用 componentDidMount 。所以我将这些代码放在 componentWillMount 中,并按如下方式更新源代码

document.addEventListener("DOMContentLoaded", function(event) {
  const node = document.getElementById('table');
  node.style.marginTop = `-${height}`;
});

然后还有其他问题。

document is not defined on server 

我知道原因,这是因为代码在节点环境中运行。浏览器环境没有文档种类。我能想到的一种方法是将代码放在 renderPage函数中,该函数用于将React组件呈现给服务器端Server Rendering上的html字符串。但是如果将事件处理程序放在顶级上下文中,它将污染其他呈现的页面。

router.get('*', ctx => {
  match({ routes: routes, location: ctx.url }, (err, redirect, props) => {
    if (err) {
      ctx.throw(err.message, 500);
    } else if (redirect) {
      ctx.redirect(redirect.pathname + redirect.search)
    } else if (props) {
      const appHtml = renderToString(<RouterContext {...props}/>);
      ctx.body = renderPage(appHtml);
    } else {
      ctx.throw(404, 'not fount');
    }
  })
})
function renderPage(appHtml) {
  return `
    <!doctype html public="storage">
    <html>
    <meta charset=utf-8/>
    <title>My First React Router App</title>
    <div id=app>${appHtml}</div>
    <script type='text/javascript'>
      document.addEventListener("DOMContentLoaded", function(event) {
        const node = document.getElementById('table');
        node.style.marginTop = `-${height}`;
      });
    </script>
  `
}

我也找到了其他解决方案。 A React component for binding events on the global scope.。我不认为它是最好的解决方案。

所以我想问一下,有更好的方法来操作DOM节点,通常放在 componentDidMount componentDidUpdate 中,就像客户端渲染一样。

1 个答案:

答案 0 :(得分:0)

像这样操纵DOM节点就像没用一样。 React接管你的DOM的控制权,在你下次重新渲染应用程序后,你设置的边距将被React覆盖。

我建议您使用内联样式来操作您想要处理的任何样式。

render() {
  const divStyle={'marginTop': '100px'}

  return <div style={divStyle}></div>
}

还让渲染功能处理UI内容。

是否有任何理由需要在React生命周期中重置marginTop而不是直接在渲染函数中重置?