<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Chen Ni</title>
    <description>The latest articles on DEV Community by Chen Ni (@chenni).</description>
    <link>https://dev.to/chenni</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F520523%2Fee6e27f4-023b-49eb-a15a-b98607866bcc.jpeg</url>
      <title>DEV Community: Chen Ni</title>
      <link>https://dev.to/chenni</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/chenni"/>
    <language>en</language>
    <item>
      <title>How to Persist Components Between Pages in Next.js (And why it works)</title>
      <dc:creator>Chen Ni</dc:creator>
      <pubDate>Thu, 16 Dec 2021 13:53:44 +0000</pubDate>
      <link>https://dev.to/chenni/how-to-persist-components-between-pages-in-nextjs-and-why-it-works-1hg8</link>
      <guid>https://dev.to/chenni/how-to-persist-components-between-pages-in-nextjs-and-why-it-works-1hg8</guid>
      <description>&lt;p&gt;The biggest question I had about Next.js (as an SSR framework) is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If the pages are rendered on the server-side, how can I persist components (like a header) between page changes?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Turns out the presumption is wrong. &lt;a href="https://dev.to/chenni/best-of-both-worlds-how-navigation-works-in-nextjs-3085"&gt;Next.js actually uses client-side rendering for page navigation&lt;/a&gt;. In other words, a Next.js app behaves just like a regular SPA, except for the first page you request from it (which is rendered on the server).&lt;/p&gt;

&lt;p&gt;But it's not that simple either. If you put a common component (imported from somewhere in your &lt;code&gt;/components&lt;/code&gt; folder) in two different pages (defined in &lt;code&gt;/pages&lt;/code&gt;) in Next.js, then the component will actually be re-rendered when you navigate from one page to the other.&lt;/p&gt;

&lt;p&gt;Let's take a real example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F046y4i7bmvbrab6usc91.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F046y4i7bmvbrab6usc91.gif" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to &lt;a href="https://nextjs.org/blog" rel="noopener noreferrer"&gt;https://nextjs.org/blog&lt;/a&gt; (it's built with Next.js);&lt;/li&gt;
&lt;li&gt;In the inspector, change the background of the header to yellow;&lt;/li&gt;
&lt;li&gt;Click the "Analytics" link in the header to navigate to &lt;a href="https://nextjs.org/analytics" rel="noopener noreferrer"&gt;https://nextjs.org/analytics&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;Notice that the yellow background disappeared. This means the header - even though consistent between the 2 pages - is re-rendered.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(Or you can create a new Next.js project and test it yourself.)&lt;/p&gt;

&lt;p&gt;This is not what we would expect from client-side rendering. It doesn't make sense to re-render the same component if the page is rendered on the client-side!&lt;/p&gt;

&lt;h2&gt;
  
  
  The Custom &lt;code&gt;App&lt;/code&gt; Component
&lt;/h2&gt;

&lt;p&gt;In Next.js, the correct way to persist components between page changes is to use &lt;a href="https://nextjs.org/docs/advanced-features/custom-app" rel="noopener noreferrer"&gt;the custom &lt;code&gt;App&lt;/code&gt; component&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It's quite simple. All you have to do is to create the file &lt;code&gt;/pages/_app.js&lt;/code&gt; if it doesn't exist already, and add the components you want to persist in there.&lt;/p&gt;

&lt;p&gt;For example, the following code will persist the &lt;code&gt;&amp;lt;Layout /&amp;gt;&lt;/code&gt; component between page changes:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// pages/_app.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Layout&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../components/layout&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MyApp&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pageProps&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="c1"&gt;// Add your header, footer, etc. in Layout and they will persist&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Layout&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="c1"&gt;// Don't change this. `Component` will be set to the current page component&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;pageProps&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Layout&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;MyApp&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;But why do we have to use this &lt;code&gt;App&lt;/code&gt; component? What's happening under the hood?&lt;/p&gt;

&lt;h2&gt;
  
  
  How Next.js Renders Your Page
&lt;/h2&gt;

&lt;p&gt;To answer the above question, we have to understand what really happens when you navigate from one page to another in Next.js.&lt;/p&gt;

&lt;p&gt;Let's say you are navigating from the page &lt;code&gt;&amp;lt;Foo /&amp;gt;&lt;/code&gt; to the page &lt;code&gt;&amp;lt;Bar /&amp;gt;&lt;/code&gt; (defined in &lt;code&gt;pages/foo.js&lt;/code&gt; and &lt;code&gt;pages/bar.js&lt;/code&gt; respectively) by clicking a Next.js link. Here is what will happen:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The JavaScript code of the new page component &lt;code&gt;&amp;lt;Bar /&amp;gt;&lt;/code&gt; is fetched from the server, if it's not already prefetched; &lt;/li&gt;
&lt;li&gt;Next.js will call &lt;code&gt;ReactDOM.render()&lt;/code&gt; with 2 arguments: the first one is the new React element to render (it can be roughly thought of as the updated &lt;code&gt;App&lt;/code&gt; component), and the second one is the DOM container element (it's always &lt;code&gt;&amp;lt;div id="__next"&amp;gt;&amp;lt;/div&amp;gt;&lt;/code&gt;) that the new React element is rendered into.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In short, this process can be roughly thought of as rendering the updated &lt;code&gt;App&lt;/code&gt; component into the &lt;code&gt;&amp;lt;div id="__next"&amp;gt;&amp;lt;/div&amp;gt;&lt;/code&gt; DOM container element. React will then take care of diffing the new and old React elements and decide which part of the DOM to re-render and which part to update.&lt;/p&gt;

&lt;p&gt;So what does the new and old React element look like? Well, the default definition of the &lt;code&gt;App&lt;/code&gt; component looks like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../styles/globals.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MyApp&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pageProps&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Component will be set to the current page component&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;pageProps&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;MyApp&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Where the &lt;code&gt;Component&lt;/code&gt; variable will be set to the current page component. This means the old React element will look like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Foo&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;pageProps&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;and the new React element will look like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Bar&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;pageProps&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;According to the &lt;a href="https://reactjs.org/docs/reconciliation.html" rel="noopener noreferrer"&gt;React diffing algorithm&lt;/a&gt;, when comparing the new and old React element, if the two elements being compared are of different types, then the corresponding subtree will be entirely destroyed and re-rendered.&lt;/p&gt;

&lt;p&gt;That's exactly what happens in this case. &lt;code&gt;&amp;lt;Foo /&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;Bar /&amp;gt;&lt;/code&gt; are two different components and are considered as of different types, so the part of the DOM that corresponds to &lt;code&gt;&amp;lt;Foo /&amp;gt;&lt;/code&gt; will be destroyed and re-rendered as &lt;code&gt;&amp;lt;Bar /&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That's why the entire page component will be re-rendered when you navigate to a new page, even if they include common components like the header.&lt;/p&gt;

&lt;p&gt;And that's why the custom &lt;code&gt;App&lt;/code&gt; component approach works. If you're using the suggested custom &lt;code&gt;App&lt;/code&gt; component above, then the old React element will look like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Layout&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Foo&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;pageProps&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Layout&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;and the new React element will look like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Layout&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Bar&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;pageProps&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Layout&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In this case, the page component &lt;code&gt;&amp;lt;Foo /&amp;gt;&lt;/code&gt; is still going to be destroyed and re-rendered as &lt;code&gt;&amp;lt;Bar /&amp;gt;&lt;/code&gt;, but &lt;code&gt;&amp;lt;Layout /&amp;gt;&lt;/code&gt; will persist.&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Best of Both Worlds: How navigation works in Next.js</title>
      <dc:creator>Chen Ni</dc:creator>
      <pubDate>Tue, 16 Nov 2021 16:01:45 +0000</pubDate>
      <link>https://dev.to/chenni/best-of-both-worlds-how-navigation-works-in-nextjs-3085</link>
      <guid>https://dev.to/chenni/best-of-both-worlds-how-navigation-works-in-nextjs-3085</guid>
      <description>&lt;h2&gt;
  
  
  Server-Side Rendering, Client-Side Navigation
&lt;/h2&gt;

&lt;p&gt;Next.js is best known for being an SSR (Server-Side Rendering) framework, but it does support client-side navigation. This means you can expect a partial reload when navigating between your pages, just like with a regular SPA app. Great in terms of user experience!&lt;/p&gt;

&lt;p&gt;But wait. With client-side navigation, the new page is rendered by JS on the client side rather than on the server side. Does this really make sense for an SSR framework? &lt;/p&gt;

&lt;p&gt;After all, the whole point of using an SSR framework is to avoid client-side rendering, so that web crawlers can index the entire page even if they don't run JS, which results in a better SEO result.&lt;/p&gt;

&lt;p&gt;This turns out not to be a problem for Next.js nagivations. In fact, if you disable JS in your browser (&lt;a href="https://developers.google.com/web/tools/chrome-devtools/javascript/disable"&gt;here is how in Chrome&lt;/a&gt;), you will see that page navigation still works in your Next.js website.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Does It Actually Work?
&lt;/h2&gt;

&lt;p&gt;What's really happening is, every &lt;code&gt;&amp;lt;Link&amp;gt;&lt;/code&gt; component in Next.js has this &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; tag under the hood. When you click on the link, some JS will run to render the new page and prevent the default &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; navigation.&lt;/p&gt;

&lt;p&gt;When JS is disabled, client-side navigation won't work, but the default &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; navigation still works. The new page will be rendered on server side, then fetched and reloaded on the client side. And that's exactly what web crawlers need to navigate between your pages. &lt;/p&gt;

&lt;h2&gt;
  
  
  Best of Both Worlds
&lt;/h2&gt;

&lt;p&gt;The Next.js navigation really is the best of both worlds:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Traditional Website&lt;/th&gt;
&lt;th&gt;SPA&lt;/th&gt;
&lt;th&gt;Next.js&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Worse User Experience&lt;/td&gt;
&lt;td&gt;Better User Experience&lt;/td&gt;
&lt;td&gt;As Good As SPA！&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Better SEO Results&lt;/td&gt;
&lt;td&gt;Worse SEO Results&lt;/td&gt;
&lt;td&gt;As Good As Traditional Website!&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>nextjs</category>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
