【问题标题】:How to make components consist between pages?如何使组件在页面之间包含?
【发布时间】:2020-09-26 17:12:47
【问题描述】:

当您从索引页面转到 about 页面时,RestOfTheApp 会重新呈现。或许 SSR 应该是这样的,但是 nextjs 像 gatsby 一样添加了静态渲染。没有办法防止组件重新渲染吗?比如:标题不应该在页面之间改变。

关于.js

function index() {
  return (
    <>
        <RestOfTheApp> 
          about
        </RestOfTheApp>
    </>
  )
}

index.js

 function index() {
      return (
        <>
        <RestOfTheApp> 
          index
        </RestOfTheApp>
        </>
      )
    }

我假设你可以使用 redux 保持组件状态,但是当你只需要获取一些博客内容时重新渲染整个页面似乎很臃肿。我已经用一些基本布局进行了测试,它看起来仍然像闪电一样快,但不重新渲染整个页面是 SPA 的主要概念,我有点心碎????

【问题讨论】:

    标签: next.js


    【解决方案1】:

    无论您做什么,您包含在页面中的每个组件(在/pages 下)都会重新呈现。但是绝对可以添加一个不会在 NextJs 中重新渲染的持久布局。解决方案是自定义应用程序组件。你可以阅读更多关于它here

    以下示例有助于了解如何创建持久布局:

    // /pages/_app.js
    
    import React from 'react';
    import App from 'next/app';
    import Layout from '../components/Layout';
    
    class MyApp extends App {
      render() {
        const { Component, pageProps } = this.props
    
        return (
          <Layout>
            <Component {...pageProps}></Component>
          </Layout>
        )
      }
    }
    
    export default MyApp 
    

    在这种情况下,当您在页面之间导航时,Layout 组件将不会重新呈现。

    【讨论】:

    • 非常感谢。我刚刚制作了一个包含页面之间的标题组件。 Nextjs 有点奇怪,但我喜欢它
    • 非常感谢!这绝对应该是公认的答案@AliMertCakar
    【解决方案2】:

    @Ankit 已经就如何创建持久化组件给出了很好的答案。这是我关于为什么它有效的两分钱。

    那么当您从某个页面 A(在 pages/a.js 中定义)导航到另一个页面 B(在 pages/b.js 中定义)时,究竟会发生什么?首先,导航发生在客户端。这意味着不是从服务器获取呈现的 HTML,而是在浏览器中运行一些 JavaScript 来呈现新页面。 (您可以验证它here。)页面导航的JavaScript逻辑归结为:

    1. 如果尚未预取新页面组件&lt;B /&gt; 的 JavaScript 代码,则从服务器获取;
    2. Next.js 将调用 ReactDOM.render() 并带有 2 个参数:第一个是要渲染的新 React 元素(可以大致认为是更新后的 App 组件),第二个是 DOM 容器元素(总是&lt;div id="__next"&gt;&lt;/div&gt;)新的 React 元素被渲染到。

    简而言之,这个过程大致可以认为是将更新后的App 组件渲染到&lt;div id="__next"&gt;&lt;/div&gt; DOM 容器元素中。然后,React 将负责区分新旧 React 元素,并决定 DOM 的哪一部分重新渲染以及更新哪一部分。

    那么新旧 React 元素是什么样子的呢?嗯,App 组件的默认定义是这样的:

    import '../styles/globals.css'
    
    function MyApp({ Component, pageProps }) {
      // Component will be set to the current page component
      return <Component {...pageProps} />
    }
    
    export default MyApp
    

    Component 变量将设置为当前页面组件。这意味着旧的 React 元素将如下所示:

    <A {...pageProps} />
    

    新的 React 元素将如下所示:

    <B {...pageProps} />
    

    根据React diffing algorithm,在比较新旧React元素时,如果被比较的两个元素是不同类型的,那么对应的子树将被完全销毁并重新渲染。

    这正是在这种情况下发生的事情。 &lt;A /&gt;&lt;B /&gt; 是两个不同的组件,被认为是不同的类型,所以 DOM 中与 &lt;A /&gt; 对应的部分将被销毁并重新渲染为 &lt;B /&gt;

    这就是为什么当你导航到一个新页面时整个页面组件会被重新渲染,即使它们包括像标题这样的常见组件。

    如果你把 header 放在自定义的App 组件中,像这样:

    import Header from '../components/header'
    
    function MyApp({ Component, pageProps }) {
      return (
        <div>
          <Header />
          <Component {...pageProps} />
        </div>
      )
    }
    
    export default MyApp
    

    然后&lt;Header /&gt; 组件将在页面导航中持续存在,因为 React diffing 算法会将其视为同一类型,并且只会对子树进行最少的更新。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-30
      • 2014-02-16
      • 2021-06-18
      • 2015-05-11
      • 1970-01-01
      相关资源
      最近更新 更多