React 19 just got delayed

Issue #299.June 20, 2024.2 Minute read.
Bytes

Today’s issue: Relicensing rug-pulls, Gen-Z’s favorite browser feature, and a new Vue package that would definitely be banned at Hogwarts.

Welcome to #299.


Eyeballs logo

The Main Thing

TkDodo wearing a sign that says, free suspense

Lord Dodo, protector of SPAs

React 19 just got delayed

And unlike Dune 2, it’s not because of the writer’s strike. It’s because an unexpected hero led a rebellion with a bunch of followers united by a righteous cause.

Ok, so kind of like Dune 2. Let’s break it down.

What happened: Last month’s React 19 RC added lots of new features that we already covered, plus one sneaky change to <Suspense /> that we didn’t.

If you’re unfamiliar, <Suspense /> is a React component that lets you display a fallback until its children have finished loading (or fetching any data they need).

Historically, all the requests inside <Suspense />’s child components would happen in parallel – which is awfully convenient for libraries like React Query where fetching usually happens at the nested component level.

However, with React 19 RC, instead of fetching in parallel, all the child components fetch sequentially. As you can imagine, taking something that used to run in parallel and making it run sequentially could have pretty massive performance implications – as TkDodo discovered.

How this happened: Over the past few years, the React team has pushed server-side features like RSC as the #blessed way to fetch data. But today, the majority of React devs are still fetching data on the client, creating a gap between the React team’s future vision of the library and its current reality.

This explains why, when TkDodo and others first complained about the new Suspense issue, the React team pushed back – saying that Suspense was never intended for client-side data fetching.

What happens next: Thankfully, after a 72-hour standoff, the React team relented. Instead of breaking popular libraries like @tanstack/react-query and @react-three/fiber, they chose to delay the React 19 general release until they can come up with a better solution for SPAs using <Suspense />.

Bottom Line: It would be a bad outcome if the React community’s reaction to this saga is “haha, we bullied React into changing their position on lazy fetching”. You should still design APIs that encourage/support prefetching as the default. – at least, that’s what I’m told.

        

Socket logo

Our Friends
(With Benefits)

A lady lying on the floor wearing a dress that is the same pattern as the carpet

The malware hiding in the npm package you just installed

Secure your dependencies with Socket

You know how there’s a new story on Hacker News every week about a company’s security being crippled by a rogue npm package?

Don’t be that company. Use Socket.

Their developer-first security platform scans the actual code of all your dependencies – so it can proactively detect and block 70+ signals of supply chain risk in open source code.

Socket is beloved by engineers at Figma, Vercel, Replit, Expo, and more – here’s why:

Start using Socket for free and protect your team from supply chain attacks – which rose by a whopping 700% in the last year alone.


Spot the Bug logo

Spot the Bug

Sponsored by CodeRabbit

Their AI-powered code reviewer gives you context-aware feedback on your PRs to help you catch bugs and save time. It’s the #1 most installed AI app on GitHub, comes with a 7-day free trial, and the pro version is completely free for OSS projects.

function getNumber() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const randomNumber = Math.random();
      if (randomNumber > 0.5) {
        resolve(randomNumber);
      } else {
        reject("Number is too low");
      }
    }, 1000);
  });
}

async function printNumber() {
  const number = await getNumber();
  console.log("The number is:", number);
}

printNumber();

Cool Bits logo

Cool Bits

  1. Geoff Graham wrote about Conditionals on custom properties and how we might be close to seeing :if() functions come to CSS.

  2. Umar Hansa wrote about building Blazing fast websites with Speculation Rules, the new browser feature that the youths can’t get enough of.

  3. Vladyslav Zubko wrote about BEM modifiers in pure CSS nesting.

  4. Roger Bannister was the first person to run a four-minute mile, but Ollie Bannister just became the first person to write a 2,800-word deep dive on Runtime environments & package management in the JS ecosystem in 2024. It does a great job comparing all the next-gen tools with the OG’s to help you choose the best option for your next project. [sponsored]

  5. Chad Whitacre wrote about Relicensing and Rug Pulls, which has to be the name of a Panic! At The Disco song, right?

  6. Daniel Nagy wrote about Experimenting with React Server Components and Vite, if you’re interested in going deeper down the RSC rabbit hole than you’ve ever been before.

  7. htmx 2.0 was just released to end support for Internet Explorer, tighten up some defaults, and tease us with a good time.

  8. Are you using the same platforms and apps as last year? How well-paid do you feel? Take part in the most complete survey Developer Nation has ever created, and you can help shape web dev trends like these and win some amazing prizes. Upon completion, you’ll get free access to the Virtual Goody Bag and enter some next-level prize draws. [sponsored]

  9. We made this interactive deep dive on Why, When, and How React renders. If this doesn’t help you understand React rendering, nothing will.

  10. Kitbag Router is a new, type-safe router for Vue.js. I know that “kitbag” is a British term for a bag you put your soccer stuff in, but it sounds like a swear word for Hogwarts students.


Spot the Bug logo

Spot the Bug: Solution

Sponsored by CodeRabbit

The printNumber function is not handling the promise rejection. To fix this, you can add a try/catch block around the await statement:

function getNumber() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const randomNumber = Math.random();
      if (randomNumber > 0.5) {
        resolve(randomNumber);
      } else {
        reject("Number is too low");
      }
    }, 1000);
  });
}

async function printNumber() {
  try {
    const number = await getNumber();
    console.log("The number is:", number);
  } catch (error) {
    console.log("Woops:", error);
  }
}

printNumber();