React 19 New Release with Amazing Changes!

The Javascript world is buzzing with excitement as React 19, the latest version in the React ecosystem, promises groundbreaking changes that could reshape the way we develop web applications. This release isn’t just another update; it introduces the revolutionary React Compiler, poised to streamline development by automating tasks traditionally handled by hooks. In this article, we’ll delve into the remarkable changes brought by React v19 and explore its potential to transform the landscape of React development.

React Compiler

At the heart of React v19 lies the new React Compiler, a game-changer that converts React code into regular JavaScript. This unexpected but innovative approach aims to boost performance, potentially doubling the speed of React applications. Due to the popular virtual dom react’s rendering approach, unlike the fine-grained-reactivity approach, in virtual dom approach we might get updates to the dom of the browser that are outside the specific nodes(areas) that needs to be re-render. The React Compiler automates optimization tasks and memoization, eliminating the need for explicit memoization hooks like useMemo, useCallback, and memo. This shift promises a more efficient and intuitive development experience, freeing developers from the burden of manual optimization. One of the core ideas here is to take away the responsibility of optimization from engineers and apply those performance improvement by automatic process, in this case, React’s compiler.

With And Without Compiler

With Compiler
Without Compiler

In the photos, we can see the same application rendering UI while producing the finalized code without React’s new compiler (current, todays state) and with React’s compiler. we can see that we have a lot of new parts that are “gray blocks”(no work, green ones means yes work, yes rendering) which means that the same app had less rendering needs to be done to achieve the same user experience.

In those two examples we can see how pre-compiling reacts code with reacts own compiler. The optimization done behind the scene by the compiler yields a pretty large chunks of rendering parts un-touched.

React Hooks

With the advent of the React Compiler, the traditional approach to handling hooks undergoes a significant transformation. Hooks like useMemo, useCallback, and memo are replaced by the React Compiler’s optimization capabilities. Instead of manually memoizing components and values, developers can rely on the compiler to optimize and memoize as needed, simplifying code and reducing boilerplate.

Use hook
A new hook meant to help improve async experience for users and suspend further rendering and handle error much better. The use hook is fed with async behaviour (like promise) and is integrated with suspense and error boundary of react.

When called with a Promise, the use Hook integrates with Suspense and error boundaries. The component calling use suspends while the Promise passed to use is pending. If the component that calls use is wrapped in a Suspense boundary, the fallback will be displayed. Once the Promise is resolved, the Suspense fallback is replaced by the rendered components using the data returned by the use Hook. If the Promise passed to use is rejected, the fallback of the nearest Error Boundary will be displayed.

React Dev Canary Docs

Unlike other react hooks, use can be used within condition like “if” and loops like “for”. let’s take a look below example:

"use client";

import { use, Suspense } from "react";
import { ErrorBoundary } from "react-error-boundary";

export function MessageContainer({ messagePromise }) {
  return (
    <ErrorBoundary fallback={<p>⚠️Something went wrong</p>}>
      <Suspense fallback={<p>⌛Downloading message...</p>}>
        <Message messagePromise={messagePromise} />
      </Suspense>
    </ErrorBoundary>
  );
}

function Message({ messagePromise }) {
  const content = use(messagePromise);
  return <p>Here is the message: {content}</p>;
}

useFormState

We can forward useFormState a form action function and initial state of data. at later stage it will return new action that we can use in our form which is based on user input. meaning our UI needs to change base on user input, and here reacts steps in, further than any before as a ui library and try to provide engineers the ability to control more of the form itself.

import { useFormState } from "react-dom";

async function increment(previousState, formData) {
  return previousState + 1;
}

function StatefulForm({}) {
  const [state, formAction] = useFormState(increment, 0);
  return (
    <form>
      {state}
      <button formAction={formAction}>Increment</button>
    </form>
  )
}

Should we use it? we’ll there are few challenges with useFormState hook and action in Form and overall more control provided by react over forms. The biggest challenge is the fact that react is a UI library, mainly built for high performance rendering. at least at the early days of react. which means that over time features that step outside of react original goal might not be maintained for the long run. Another problem here is that forms and data validation of data provided by user input is something that never been completely solved. There’s no a single go to library to do input and form validation, there’s no single approach or design pattern to do so.

useOptimistic
This hook allow us to show different state while an async action is ongoing, it accepts a state and returns copy of that state that can change over time of the async action. A good example would be network request.

import { useOptimistic } from 'react';

function AppContainer() {
  const [optimisticState, addOptimistic] = useOptimistic(
    state,
    // updateFn
    (currentState, optimisticValue) => {
      // merge and return new state
      // with optimistic value
    }
  );
}

Looks like optimistic new hook is inspired by “perceived performance” approach where the assumption of the engineer is that user actions are 99.9% likely to succeed and it’s best to present a positive msg but in case we have error we’ll change the msgs immediately afterwards. For more about use optimistic, click here to read more.

Simplified Refs

In the React Compiler paradigm, the handling of refs takes a more straightforward approach. The concept of forwardRef gives way to a simpler mechanism where ref becomes a regular prop, effortlessly passed down through component hierarchies. This simplification streamlines the usage of refs, treating them like any other prop and eliminating the need for cumbersome forwardRef wrappers.

Actions

Here React’s team attempt to ease the way the UI communicate with the backend, database and data mutation server side. As part of the server components React team wants to allow engineers a way to send data server side and client side with the same code. it could possible be the new way we’ll be performing async actions but it could be a new deprecated code we’ll be adding to our project because Actions Reaching outside of react’s realm. Let’s take a look at actions example code within a form html tag:

<form action={search}>
  <input name="query" />
  <button type="submit">Search</button>
</form>

Above function, Action can run async an sync, Client side and Server Side (using ‘use server’ directive). Within the javascript eco system it’s not the first time someone trys to solve the client and server side code, or in other words: universal rendering, isomorphic rendering and other names come to mind when we look at React’s Action.

More

  1. support for web components.
  2. <Provider.context> change to <Context>
  3. Offscreen (rename to Activity) – right now this feature won’t be part of react 19
    • an approach regards content that is not visible and inactive or is visible and inactive (and not need to be re-rendered) e.g: content behind popup/modal
  4. “use client” and “use server” – a way to ease full stack development.
  5. Document Metadata – a way to ease SEO improvements like meta data, browser title etc.
  6. Asset Loading – coming wtihin reacts, no longer we’ll need to buil work arounds with javscript
    • but again it might be outside of react world which means you might still want to use a separate library and not couple yourself to react for asset loading.

Summary

React as a library is in generally speaking in a good, stable, mature place. Meaning that there are no changes that will shift something within react, and how the syntax is written. it’s both good and bad, it’s good because it means that we can relay on react’s current version and stability to stay the way that it is mostly for the upcoming few years. It’s bad because it might means that there are no changes that will bring react to the next level, in fact, maybe, besides changing the rendering approach of virtual DOM (or adding a new compiler) there’s no much that react can do to take us to the next level, because we are already there. In regards to upcoming features, It’s best to take them with grain of salt, as in some cases we see React team breaking outside of what React original idea is.

Leave a Reply

Your email address will not be published. Required fields are marked *

All rights reserved 2024 ©