>
Published on

Migrating from React to Next.js 13: Client, Hydration, Routing Issues Ahead

Authors

Migrating from React to Next.js 13

In recent years, Next.js has emerged as a powerful framework for building modern, high-performance web applications. With its seamless integration of server-side rendering, static site generation, and API routes, Next.js has gained popularity among developers seeking to optimize their projects for performance and SEO. The release of Next.js 13 brings even more enhancements and features to the table, making it an exciting time to consider migrating from React to Next.js. In this article, we'll explore the benefits of Next.js 13 and dive into the crucial aspect of routing in Next.js, comparing server-side and client-side components.

my project

Why Migrate from React to Next.js?

React has long been a popular choice for building dynamic and interactive user interfaces. However, as applications grow in complexity, the need for efficient server-side rendering (SSR) and improved performance becomes paramount. This is where Next.js, a framework developed by Vercel, comes into the picture. Vercel, the company behind Next.js, provides a robust platform with a wide array of features and a generous free tier, making it an appealing choice for developers. In addition to Next.js applications, Vercel also allows you to host React frontend projects. This means that if you're not ready to migrate your entire application to Next.js, you can still take advantage of Vercel's platform and its performance optimizations by hosting your React frontend projects seamlessly. Here are a few key reasons why developers are considering migrating from React to Next.js:

Built-in API Routes

Next.js provides a straightforward way to define API routes within your application. This feature enables you to create serverless functions that can handle API requests, further simplifying your backend logic. Whether you need to fetch data from a third-party API or perform server-side computations, Next.js API routes have got you covered.

Generous Free Tier

Vercel offers a very generous free tier of its service, allowing developers to host and deploy Next.js applications without incurring additional costs. This makes it an attractive option for developers who want to experiment, prototype, or launch small-scale projects without financial constraints.

Server-side Rendering and Performance Optimization

Next.js provides built-in server-side rendering (SSR) and static site generation (SSG) capabilities. This means that your web pages can be pre-rendered on the server and sent as HTML to the client, resulting in faster initial page loads and improved search engine optimization (SEO). Next.js 13 brings even more performance optimizations, making it an enticing choice for developers looking to enhance the speed and efficiency of their applications.

Migration Issues Encountered

New Client-side Components (CSCs) Tagging

Client-side components in Next.js are React components that are rendered on the client-side, utilizing JavaScript to handle interactivity and dynamic updates. These components are loaded and rendered after the initial page load, enhancing the user experience by providing interactive elements and real-time updates.

To ensure smooth functionality, it's important to declare all components that use the useState hook with the code use client. This declaration tells Next.js to handle the state management on the client-side, optimizing the rendering and updating process.

'use client'
import React, { useState } from 'react'

By using this code block, you explicitly indicate that the following components will utilize the client-side rendering capabilities of Next.js and leverage the useState hook for state management.

Next.js employs an intelligent strategy called code splitting to optimize the loading of client-side components. Only the required JavaScript code for the current page is loaded, reducing the overall bundle size and improving performance. This approach enables Next.js to strike a balance between initial load time and subsequent interactivity.

By utilizing client-side components and the use client declaration, you can create dynamic and responsive user interfaces that provide seamless interactivity and real-time updates, taking your Next.js application to the next level.

Hydration Issues from Older Projects and Material UI Interactions

During the migration process, I encountered a hydration issue while rendering a login page from an older React project. This issue occurred when trying to render the server-generated HTML on the client-side. It resulted in warnings and errors such as:

  • Warning: Did not expect server HTML to contain a <div> in <div>.
  • Warning: An error occurred during hydration. The server HTML was replaced with client content in <#document>.
  • Uncaught Error: Hydration failed because the initial UI does not match what was rendered on the server.
  • Uncaught Error: There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.

To address these issues, I had to make use of the NoSsr component from Material UI. The NoSsr component is designed to prevent server-side rendering and ensures that certain components only render on the client-side. By wrapping the login component with NoSsr, I was able to overcome the hydration issues and ensure a smooth migration process for my login page from the older React project.

import NoSsr from '@mui/base/NoSsr';
const LoginPage = () => {
  ...
  return (
    <NoSsr>
        <div>
          <form>
            <TextField/>
            <TextField/>
            <Button>
              Sign In
            </Button>
          </form>
        </div>
    </NoSsr>
  );
};
export default LoginPage;

If you're interested in exploring the complete source code of the login page and its associated components, you can find it on GitHub at https://github.com/smmk123/sample-store-njs/tree/main/app/login. Feel free to review the code and see how the NoSsr component is implemented to address the hydration issues encountered during the migration process.

Next.js 13's Routing Structure

One of the notable features introduced in Next.js 13 is its improved routing structure, which adopts a folder-based approach similar to other popular frameworks like Django and Angular. This new routing structure requires a bit of refactoring for old projects.

In Next.js 13, each folder within the /app directory represents a segment of the website's main URL path. For example, if you have a folder named blog within the /app directory, it will correspond to the /blog path on your website. This folder-based structure provides a natural and intuitive way to organize your application's pages and routes.

To render content for a specific route, you need to have a page.tsx file inside the corresponding folder. This page.tsx file acts as the entry point for rendering content related to that specific route. For instance, if you have a file named page.tsx within the blog folder, it will be responsible for rendering content when accessing the /blog route.

sample of folder structure

If you're looking for a more in-depth exploration of Next.js 13's app directory and routing structure, I recommend checking out the excellent article here. This article dives into the details of how the folder-based routing works in Next.js 13 and provides valuable insights and examples to help you understand and leverage this new feature effectively.

It's important to note that while Next.js 13 simplifies the routing structure, you can still leverage third-party libraries like React Router if you have more complex routing requirements or prefer a different routing approach. Next.js allows you to seamlessly integrate with React Router, enabling you to continue using its powerful routing capabilities within your Next.js application.

Conclusion and Next Steps

In this article, we explored the migration process from React to Next.js 13, highlighting the benefits and features that make Next.js an appealing choice for developers.

We also touched upon the migration issues encountered, particularly hydration issues and how they can be resolved using techniques such as the NoSsr component from Material UI. Additionally, we discussed Next.js 13's folder-based routing structure, which simplifies defining routes and provides a familiar approach for developers coming from other frameworks like Django and Angular.

To further enhance the project, I plan on integrating NextAuth.js, a popular authentication library for Next.js. NextAuth.js provides seamless authentication support with various providers, ensuring that only authenticated users can access certain pages. I will then add the protected routes for the Admin of the site.

if you would like to see a live view of the store you can go here. If you'd like to explore the project's source code, you can find it here. Keep in mind that the project is still a work in progress, and you have the opportunity to add NextAuth.js and implement route protection to enhance the security and functionality of your application.

Migrating from React to Next.js opens up a world of possibilities, combining the power of React with the benefits of server-side rendering and improved performance. With Next.js 13's intuitive routing structure and the potential integration of NextAuth.js, you're well on your way to building a robust and secure web application. Happy coding!