在official docs中,显示为React will attempt to attach event listeners to the existing markup.
所以我以为,如果我使用ReactDOM.hydrate,它只会添加事件。
// server.js
app.get('/', (req, res) => {
const html = fs.readFileSync(path.resolve('./build/index.html'), 'utf8');
return res.send(
html.replace(
'<div id="root"></div>',
'<div id="root">hihi</div>',
),
);
}
// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.hydrate(
<App/>,
document.getElementById('root'),
);
// App.jsx
import React from 'react';
import styled from 'styled-components';
export default () => {
return <Title}>Hi !</Title>;
};
const Title = styled.h1`
color: blue;
`;
但是,当水合物起作用时,它将删除SSR创建的DOM并将其替换为CSR创建的DOM(反应脚本)
为什么会这样?
答案 0 :(得分:0)
那不是React SSR的工作方式。您也应该在服务器端做出反应,并且可能可以在服务器端使用renderToString。这样一来,react就会知道这是服务器渲染的react节点,并且需要在客户端进行水合作用。
答案 1 :(得分:0)
您的服务器呈现的 HTML
是,
<div id="root">
hihi
</div>
您的客户端呈现的 HTML
是,
<div id="root">
<h1 style="color: blue;">Hi !</h1>
</div>
首先,浏览器加载服务器 HTML
。然后客户端开始在服务器渲染的 HTML
上重新水化,这与客户端渲染的版本有很大不同。因此,它会删除 hihi
文本,然后将 h1
元素添加到 DOM。这就是为什么您在刷新页面时会看到闪烁的原因。您可以更改您的服务器 HTML
如下以解决您的问题。
// server.js
app.get('/', (req, res) => {
const html = fs.readFileSync(path.resolve('./build/index.html'), 'utf8');
return res.send(
html.replace(
'<div id="root"></div>',
'<div id="root"><h1 style="color: blue;">Hi !</h1></div>',
),
);
}
当你尝试做一个真正的项目时,你需要在服务器端使用 ReactDOM.renderToString
。有很多文章可以开始。请检查这个 => https://medium.com/bucharestjs/upgrading-a-create-react-app-project-to-a-ssr-code-splitting-setup-9da57df2040a