React.js vs Next.js: Unpacking Their Unique Strengths
by Muradil Erkin, Founder / Senior Software Engineer / Instructor
1. Introduction to React
React's birth can be traced back to 2011 when Jordan Walke, a software engineer at Facebook, took inspiration from XHP (an HTML component library for PHP) and created a JavaScript library that would allow for building UI components. It was officially released in 2013.
React was groundbreaking in its approach. It introduced a virtual DOM, which is an in-memory representation of the real DOM elements. The rendering engine can quickly make changes to the virtual DOM and subsequently update the live DOM in a more optimized and efficient way.
2. A Glimpse at React's Basics
React is all about components — reusable pieces of UI. They encapsulate the logic required for rendering the view and maintain their own state.
Here's a basic example of a stateful React component written in TypeScript:
'use client'
import React, { useState } from 'react'
import { Button } from './Button'
import { Text } from './Text'
interface Props {
defaultCount: number
}
const Counter = ({ defaultCount }: Props): JSX.Element => {
const [count, setCount] = useState<number>(defaultCount)
return (
<>
<Button onClick={() => setCount(count - 1)}>-</Button>
<Text>{count}</Text>
<Button onClick={() => setCount(count + 1)}>+</Button>
</>
)
}
export default Counter
This Counter component has a piece of state called count which changes when you click on the buttons.
Here's how that code looks in action:
3. React's Main Purpose
React was created to simplify the process of building interactive UIs in an efficient and modular way. While traditionally associated with SPAs, its flexibility allows it to be the foundational UI library in a wide variety of projects, from mobile apps (using React Native) to virtual reality experiences.
4. Introduction to Next.js
While React excels at building SPAs, there are projects that require capabilities like server-side rendering for improved SEO and performance. This is where Next.js, developed by Vercel, comes into play. Introduced in 2016, it builds upon the core strengths of React, offering features like pre-rendering, automatic code splitting, and static exporting.
5. What Next.js is Meant For
Next.js brings server-side rendering to the table, which allows for the generation of the full HTML for a page on the server in response to a request. This means:
- Faster page loads, as users receive pre-rendered HTML.
- Improved SEO, since search engines can crawl the pre-rendered content more efficiently.
Moreover, with features like static site generation and API routes, Next.js becomes a Swiss Army knife for modern web development.
Today, Next.js has evolved into a framework that enables you to create full-stack Web applications by extending the latest React features, including React Server Componenets, Routing, and Data Fetching.
6. A Glimpse at Next.js Basics
Next.js offers a convention-based file system routing. Every file inside the pages directory becomes a route in your application. It also provides a seamless transition between client-side rendered and server-side rendered content.
Here's a basic example of a Next.js page that fetches data from an API and displays it, written in TypeScript:
import React from 'react'
import { List, Title } from '@/components'
const fetchCatFacts = async () => {
const response = await fetch('https://cat-fact.herokuapp.com/facts')
const data = (await response.json()) as any[]
const catFacts = data.map((item) => item.text as string)
return catFacts
}
const CatFacts = async () => {
const catFacts = await fetchCatFacts()
return (
<>
<Title>Cat Facts</Title>
<List items={catFacts} />
</>
)
}
export default CatFacts
This CatFacts component fetches some data about cat facts and then reders the view in the server and sends the result to the front end.
In traditional React, we'll need useEffect and useState to fetch the data from the front end and React will update the virtual dom once the data is fetched.
Here's how that code looks in action:
React vs Next.js: The Relationship
When React was conceived, its primary role was to handle the view in the MVC (Model-View-Controller) paradigm. It's a library purely meant for building user interfaces. Next.js, on the other hand, can be thought of as a framework built around React, extending its capabilities.
To put it simply, if React is the superhero of the frontend world, Next.js is that superhero with an additional set of tools and gadgets. Everything you can do in React can be achieved within Next.js, but with Next.js you get additional out-of-the-box benefits like server-side rendering, static site generation, and a built-in routing system.
Traditionally, React has been utilized for frontend development, creating Single Page Applications (SPAs) without the direct need for a backend. Next.js has evolved as a solution for those who want to take a full-stack approach with React, offering backend capabilities and solutions for SEO challenges SPAs face.
However, the landscape is changing. With recent updates, React itself has moved closer to offering some of the server-side rendering benefits that Next.js provides. This move by React demonstrates an acknowledgment of the evolving needs of modern web applications.
Yet, in a testament to Next.js's significance and strengths, even the React team, on their official site, recommends using Next.js for full-stack development. It's a powerful endorsement of Next.js's capabilities and the symbiotic relationship it shares with React.
Conclusion:
The lines between React and Next.js might seem blurred at times, but understanding their distinct and overlapping roles can guide developers in making informed choices. React remains a potent force in the frontend domain, while Next.js brings in a comprehensive solution for those looking to venture into full-stack territories.