所以我有一个使用Next.js的SSR应用程序。我正在使用利用WEB API的第三方组件,因此需要将其加载到客户端而不是服务器上。我是通过“两次通过”渲染来实现的,在这里我了解到:https://itnext.io/tips-for-server-side-rendering-with-react-e42b1b7acd57
我试图弄清楚为什么当next.js页面中的ssDone状态更改时,整个<Layout>
组件不必要地重新渲染,包括页面的Header,Footer等。
我已经了解了React.memo()
并利用了shouldComponentUpdate()
,但似乎无法阻止它重新呈现<Layout>
组件。
我的<Layout>
控制台消息触发两次,但<ThirdPartyComponent>
控制台消息触发一次。这是一个问题还是React足够聪明以至于实际上没有更新DOM,所以我什至不必担心这一点。无缘无故地重新渲染页面的页眉和页脚似乎很愚蠢。
在控制台中,输出为:
Layout rendered
Layout rendered
3rd party component rendered
index.js(next.js页面)
import React from "react";
import Layout from "../components/Layout";
import ThirdPartyComponent from "../components/ThirdPartyComponent";
class Home extends React.Component {
constructor(props) {
super(props);
this.state = {
ssrDone: false
};
}
componentDidMount() {
this.setState({ ssrDone: true });
}
render() {
return (
<Layout>
{this.state.ssrDone ? <ThirdPartyComponent /> : <div> ...loading</div>}
</Layout>
);
}
}
export default Home;
ThirdPartyComponent.jsx
import React from "react";
export default function ThirdPartyComponent() {
console.log("3rd party component rendered");
return <div>3rd Party Component</div>;
}
Layout.jsx
import React from "react";
export default function Layout({ children }) {
return (
<div>
{console.log("Layout rendered")}
NavBar here
<div>Header</div>
{children}
<div>Footer</div>
</div>
);
}
答案 0 :(得分:0)
Layout
组件重新呈现,因为其children
道具已更改。首先是<div> ...loading</div>
(当ssrDone = false
时),然后是<ThirdPartyComponent />
(当ssrDone = true
时)
答案 1 :(得分:0)
您可以做的是定义一个新的<ClientSideOnlyRenderer />
组件,它看起来像这样:
const ClientSideOnlyRenderer = memo(function ClientSideOnlyRenderer({
initialSsrDone = false,
renderDone,
renderLoading,
}) {
const [ssrDone, setSsrDone] = useState(initialSsrDone);
useEffect(
function afterMount() {
setSsrDone(true);
},
[],
);
if (!ssrDone) {
return renderLoading();
}
return renderDone();
});
您可以这样使用它:
class Home extends React.Component {
static async getInitialProps({ req }) {
return {
isServer: !!req,
};
};
renderDone() {
return (
<ThirdPartyComponent />
);
}
renderLoading() {
return (<div>Loading...</div>);
}
render() {
const { isServer } = this.props;
return (
<Layout>
<ClientSideOnlyRenderer
initialSsrDone={!isServer}
renderDone={this.renderDone}
renderLoading={this.renderLoading}
/>
</Layout>
);
}
}
这样,在初始安装后,只有ClientSideOnlyRenderer
组件会重新呈现。 ?