防止 React 在 hydrate 上重新渲染部分 SSR 内容
Prevent React from re-render partial SSR content on hydrate
如何防止 SSR 内容在 React.hydrate(...)
上在客户端浏览器中重新呈现?
我的工作流程
在我当前的项目中,我在构建过程中通过 ReactDomServer.renderToString(...)
渲染了一堆 React 组件。此渲染的结果将用作 Thymeleaf 片段。 SSR DOM 包含几个 th:text
用于内部化的属性:
简要示例
这是我的组件:
import React from "react";
class WdbThym extends React.Component {
constructor(props) {
super(props);
}
shouldComponentUpdate() {
return false;
};
render() {
return (
<span {...{ 'th:text': `#{${this.props.i18n}}` }}>
{this.props.i18n}
</span>
);
}
}
export default WdbThym;
这是 WdbThym
的用法示例:
<WdbThym i18n="general.hello_world" />
这是 ReactDomServer.renderToString(...)
创建的:
<span th:text="#{general.hello_world}">general.hello_world</span>
这是 Thymeleaf 呈现并分派给客户端的内容:
<span>Hello World!</span>
这是 React.hydrate
呈现的内容:
<span th:text="#{general.hello_world}">general.hello_world</span>
如何防止在 React.hydrate(...)
上针对上述 Component
进行初始渲染?
据@estus 报道,https://github.com/facebook/react/issues/8017 解决了这个问题。
我创建了一个稍微复杂的示例来重现给定的建议:
DOM
<div id="root">
<div class="App">
<h1>THIS IS SSR CONTENT</h1>
<p>Current Time: 2019-01-27T08:00:00.000Z</p>
<p>Hello World from Thymeleaf (SSR)</p>
</div>
</div>
反应
class CsrComponent extends React.Component {
state = { currentTime: "" };
componentDidMount = () => {
setInterval(() => {
this.setState({ currentTime: new Date().toISOString() });
}, 1000);
};
render() {
return <p>Current Time: {this.state.currentTime}</p>;
}
}
class SsrComponent extends React.Component {
render() {
return (
<p
dangerouslySetInnerHTML={{ __html: "" }}
suppressHydrationWarning
{...{ "th:text": `#{${this.props.i18n}}` }}
/>
);
}
}
class App extends React.Component {
render() {
return (
<div className="App">
<h1>THIS IS SSR CONTENT</h1>
<CsrComponent />
<SsrComponent i18n="general.hello_world" />
</div>
);
}
}
保湿
const rootElement = document.getElementById("root");
ReactDOM.hydrate(<App />, rootElement);
这个给定的例子也可以在 https://codesandbox.io/s/o5171l2v59
如何防止 SSR 内容在 React.hydrate(...)
上在客户端浏览器中重新呈现?
我的工作流程
在我当前的项目中,我在构建过程中通过 ReactDomServer.renderToString(...)
渲染了一堆 React 组件。此渲染的结果将用作 Thymeleaf 片段。 SSR DOM 包含几个 th:text
用于内部化的属性:
简要示例
这是我的组件:
import React from "react";
class WdbThym extends React.Component {
constructor(props) {
super(props);
}
shouldComponentUpdate() {
return false;
};
render() {
return (
<span {...{ 'th:text': `#{${this.props.i18n}}` }}>
{this.props.i18n}
</span>
);
}
}
export default WdbThym;
这是 WdbThym
的用法示例:
<WdbThym i18n="general.hello_world" />
这是 ReactDomServer.renderToString(...)
创建的:
<span th:text="#{general.hello_world}">general.hello_world</span>
这是 Thymeleaf 呈现并分派给客户端的内容:
<span>Hello World!</span>
这是 React.hydrate
呈现的内容:
<span th:text="#{general.hello_world}">general.hello_world</span>
如何防止在 React.hydrate(...)
上针对上述 Component
进行初始渲染?
据@estus 报道,https://github.com/facebook/react/issues/8017 解决了这个问题。
我创建了一个稍微复杂的示例来重现给定的建议:
DOM
<div id="root">
<div class="App">
<h1>THIS IS SSR CONTENT</h1>
<p>Current Time: 2019-01-27T08:00:00.000Z</p>
<p>Hello World from Thymeleaf (SSR)</p>
</div>
</div>
反应
class CsrComponent extends React.Component {
state = { currentTime: "" };
componentDidMount = () => {
setInterval(() => {
this.setState({ currentTime: new Date().toISOString() });
}, 1000);
};
render() {
return <p>Current Time: {this.state.currentTime}</p>;
}
}
class SsrComponent extends React.Component {
render() {
return (
<p
dangerouslySetInnerHTML={{ __html: "" }}
suppressHydrationWarning
{...{ "th:text": `#{${this.props.i18n}}` }}
/>
);
}
}
class App extends React.Component {
render() {
return (
<div className="App">
<h1>THIS IS SSR CONTENT</h1>
<CsrComponent />
<SsrComponent i18n="general.hello_world" />
</div>
);
}
}
保湿
const rootElement = document.getElementById("root");
ReactDOM.hydrate(<App />, rootElement);
这个给定的例子也可以在 https://codesandbox.io/s/o5171l2v59