reactjs - 如何防止父组件使用 React (next.js) SSR 两遍渲染重新渲染?

标签 reactjs next.js server-side-rendering

所以我有一个使用 Next.js 的 SSR 应用程序。我正在使用一个利用 WEB API 的 3rd 方组件,因此它需要加载到客户端而不是服务器上。我正在使用我在此处阅读的“两遍”渲染来执行此操作:https://itnext.io/tips-for-server-side-rendering-with-react-e42b1b7acd57

我试图弄清楚为什么当 next.js 页面中的“ssrDone”状态改变时,整个 <Layout>组件不必要地重新渲染,其中包括页面的页眉、页脚等。

我读过 React.memo()以及利用 shouldComponentUpdate()但我似乎无法阻止它重新渲染 <Layout>成分。

我的 console.log 消息 <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;

第三方组件.jsx
import React from "react";

export default function ThirdPartyComponent() {
  console.log("3rd party component rendered");
  return <div>3rd Party Component</div>;
}

布局.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>
  );
}

最佳答案

你可以做的是定义一个新的 <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组件在初始安装后重新渲染。 👍

关于reactjs - 如何防止父组件使用 React (next.js) SSR 两遍渲染重新渲染?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58987174/

相关文章:

javascript - AXIOS PUT 请求返回 200 代码但不更新内容?

javascript - React 未触发内部按钮 onClick 事件

node.js - 当我运行 'npm run build' 、 'npm run start' 时组件缺少类,但其他人无法重现该错误

reactjs - 下一个 JS 的 API 缓存

reactjs - 无法将 SVG 导入 Next.js

vue.js - nuxt 构建与生成

javascript - 即时将 JSX 字符串编译为组件

reactjs - 迁移到 Webpack 2 后,gulp 或 webpack-stream 导致 webpack 构建失败

vue.js - nuxt js中的自定义指令

javascript - Jest 找不到在我的测试中导入的组件