Today I Learned

TIL, 2023-07-25, React Server Components

How React 18 Improves Application Performance

Reference

  • Any task that takes more than 50ms to run is a long task.
  • This comes from the fact that devices must create a new frame every 16ms (60fps) to maintain a smooth visual experience, however, they must also perform other tasks, such as responding to JS.
  • 50ms means the devices has 33.33ms for the device to perform other tasks.
  • Total blocking time:
    • Between the First Contentful Paint and Time to Interactive.
  • Interaction to next paint: Time from a user’s first interaction with the page to when the interaction is visible on-screen, the next paint.
  • Visual update in React is divided into two phases: the render phase and the commit phase.
    • Render - computation phase where React elements are reconciled with the existing DOM.
    • React calculates the differences between the current DOM and the new React component tree and prepares the necessary updates.
  • Synchronous render - React give the same priority to all elements within a component tree.
    • During this time, the main thread is blocked. Example: search field where you do setText - there is a delay.
  • React 18: New concurrent renderer that exposes ways for us to mark certain renders as non-urgent.
    • React can pause and resume the rendering of one or multiple component trees to achieve the most optimal user experience.

Transitions

  • We can mark update as non-urgent by using startTransition.
  • When a transition starts, the concurrent renderer prepares the new tree in the background.
import { useTransition } from "react";

function Button() {
  const [isPending, startTransition] = useTransition();

  return (
    <button
      onClick={() => {
        urgentUpdate();
        startTransition(() => {
          nonUrgentUpdate()
        })
      }}
    >...</button>
  )
}
  • Fix using useTransition
import React, { useState, useTransition } from "react";
import CityList from "./CityList";

export default function SearchCities() {
  const [text, setText] = useState("Am");
  const [searchQuery, setSearchQuery] = useState(text);
  const [isPending, startTransition] = useTransition();

   return (
      <main>
          <h1><code>startTransition</code></h1>
          <input
              type="text"
              value={text}
              onChange={(e) => {
                 setText(e.target.value)
                 startTransition(() => {             <- React renders the new tree on each keystroke, but starts preparing
                    setSearchQuery(e.target.value)   <- the new version in memory while the curren UI remains responsive to
                                                     <- current user input.
                 })
             }}  />
          <CityList searchQuery={searchQuery} />
      </main>
     );
};

React Server Components

  • Send the actual serialized component tree to the client. Client-side React renderer performantly reconstructs the React component tree without sending the HTML file or JS bundle.
  • When you do use client, you tell the bundler to “add this component and its imports” to the client bundle and React to hydrate the tree client-side to act interactivity.

React Suspense

  • We delay the rendering of a component until certain conditions are met, like data being loaded.

Data Fetching

  • cache that remembers the result of the wrapped function call.

Introducing Zero-Bundle-Size React Server Components

Reference

  • react-fetch API
  • Dependencies in the server component are not a part of the bundle.
  • A client component can receive props from the server
  • Asking to re-render the server component:
    • Set a location and re-render the server tree from the root.
  • Server components vs SSR:
    • Clicking on the note to show on the right - keeps all client-rendered components don’t get blown away.
  • Shared component: Can render on the server or the component, whoever renders it dictates.
  • Suspense + Server components
  • Transitions - Defining component in a transition means you respond immediately.
  • Which components are on the server and which are on the client?
  • React IO libraries
    • react-fs, react-pg, react-fetch

Musings

  • So most of our app should honestly be server-rendered?
  • Ex: Listing page, maybe the search input, tabs, etc. is client-rendered, but banner, listing items etc. are server-rendered.
  • Then we should use useTransition more.
  • So this is why we shouldn’t probably be super invested in react-query, or at least have it alongside server components

This project is maintained by daryllxd