首页 > 解决方案 > ReactDOMServer.renderToString() - 它到底是做什么的?

问题描述

contructor()我知道它只是将 HTML 呈现为文本,所以说到类组件,只有render()renderToString(). 但是我注意到一些关于函数组件的奇怪行为。考虑以下组件示例:


function MyComponent() {

  console.log(1);

  return(
    <React.Fragment>
      Some text
    </React.Fragment>
  )
}

我只是console.log()在函数组件内部使用,我猜它相当于constructor()类组件内部的方法。

renderToString()在快速路由处理程序中调用:

import { ServerStyleSheets, ThemeProvider } from '@material-ui/core/styles';
import express from 'express';
import React from 'react';
import { renderToString } from 'react-dom/server';
import theme from 'mui/theme';
import App from 'components/App';

const SERVER_PORT = 8081; // Port for Express to listen

const app = express();

app.get('*', async (req, res) => {
  const sheets = new ServerStyleSheets();

  const inlineApp = renderToString(
    sheets.collect(
      <Provider store={exampleStore}>
        <ThemeProvider theme={theme}>
          <CssBaseline />
          <App />
        </ThemeProvider>
      </Provider>,
    ),
  );

  const css = sheets.toString();

  const renderedHTML = `
    <html lang="en">
      <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <style id="jss">${css}</style>
        <title>Repl.it</title>
      </head>
      <body>
        <div id="root">${inlineApp}</div>
        <script>
        window.STATE = ${JSON.stringify(exampleStore.getState())};
        </script>
        <script src="app.js"></script>
      </body>
    </html>
    `;

  res.send(renderedHTML);
});

app.listen(SERVER_PORT, () => {
  console.log(`Listening at http://localhost:${SERVER_PORT}`);
});

问题是我在调用ReactDOMServer.renderToString()一次时得到了两次控制台输出。我不在服务器端使用双重渲染。所以我有两个问题:

标签: reactjsserver-side-rendering

解决方案


没有足够的数据来做出明确的诊断,但可能是你在 React 的严格模式下运行?

看看这个:https ://reactjs.org/docs/strict-mode.html

严格模式不能自动为您检测副作用,但可以通过使它们更具确定性来帮助您发现它们。这是通过有意双重调用以下函数来完成的:

  • 类组件构造函数、render 和 shouldComponentUpdate 方法
  • 类组件静态 getDerivedStateFromProps 方法
  • 功能组件体
  • 状态更新函数(setState 的第一个参数)
  • 传递给 useState、useMemo 或 useReducer 的函数

如果不是这种情况......并且我实际上并没有<StrictMode>在您的代码中看到,那么如果您制作一个最小的可重现示例会很好。


另请注意,虽然函数组件主体在严格模式下调用了两次,console.log()但从React 17开始的 s被覆盖,因此您应该在控制台上只看到一条记录。但这可以改变。不是每个人都对此感到满意,现在有一个PR至少可以选择退出这种行为。


推荐阅读