preconnect

Hints that the browser should open a connection to a server you will request resources from.

Signature
preconnect(href)
  • Added in React 19.0.0

Parameters

ParameterTypeDescription
$hrefstringThe URL of the server you want to connect to.

Return value

voidNothing.

Changelog

  • PHP 19.0.0Shipped in the stable react-dom release; previously available only in Canary builds.

preconnect asks the browser to do the expensive part of talking to another origin — DNS lookup, TCP handshake, TLS negotiation — before you actually need anything from it. React emits a <link rel="preconnect">, and when the real request arrives it can skip straight to sending bytes.

When to reach for it

  • You know you will hit a third-party origin soon but not yet which URL: an image CDN whose paths depend on data still loading, a font host, an analytics endpoint.
  • A payment or media provider that only gets contacted after the user starts a flow — connect while they are still filling in the form.

What trips people up

Connections are not free. Each one holds sockets open on the client and the server, and browsers cap how many they will speculatively keep alive. Preconnecting to a dozen origins on every page typically makes things slower, not faster; keep it to the two or three that matter. If you are guessing across many domains, prefetchDNS is the cheaper hint.

Preconnecting to your own origin is pointless — the browser is already connected to it by the time the hint is processed. And if you know the exact URL, skip straight to preload or preinit: those open the connection and start the transfer.

Unused connections are dropped after a short idle timeout, so a hint fired far too early buys nothing.

Example

Example · jsx
import { useState } from "react";
import { preconnect } from "react-dom";

function CheckoutForm({ onSubmit }) {
  // The exact payment URL depends on the card the user chooses,
  // so connect to the origin now and request the URL later.
  preconnect("https://payments.example.com");

  return (
    <form onSubmit={onSubmit}>
      <label>
        Card number <input name="card" inputMode="numeric" />
      </label>
      <button type="submit">Pay</button>
    </form>
  );
}

export default function Checkout() {
  const [status, setStatus] = useState("editing");

  // Product images come from a CDN whose paths arrive with the cart data.
  preconnect("https://images.example-cdn.com");

  return (
    <main>
      <h1>Checkout</h1>
      <p>Status: {status}</p>
      <CheckoutForm
        onSubmit={(event) => {
          event.preventDefault();
          setStatus("submitted");
        }}
      />
    </main>
  );
}

When to use it

  • Connect to an image CDN while the product list is still being fetched.
  • Warm the TLS handshake to a payment provider as the checkout form mounts.
  • Prepare a font host referenced by a stylesheet that has not parsed yet.
  • Open a connection to a media server before the user presses play.

Frequently asked questions

Should I preconnect to my own domain?

No. The browser is already connected to the origin serving the page, so the hint is wasted. Use it only for third-party origins such as CDNs, font hosts, and APIs on another domain.

When is prefetchDNS the better choice?

When you are speculating across many domains and are not sure which you will use. It only resolves DNS, so the overhead is far lower than holding open TCP and TLS connections you may never need.

How many origins can I safely connect to?

Two or three that you are confident about. Browsers limit how many speculative connections they keep, and extra hints can evict the ones that would have mattered while consuming client and server resources.

More examples

Connecting to the origins a page will actually use

Both hints are emitted into the head during the first render, so the handshakes overlap with parsing the rest of the document instead of blocking the first API call. Adding a third or fourth speculative origin here would usually be counter-productive: the browser has a limited number of connections it will open on speculation, and the useful ones can be crowded out.

Example · jsx
import { preconnect } from "react-dom";

export default function AppShell() {
  // Two origins, both certain to be used on this page.
  preconnect("https://fonts.gstatic.com");
  preconnect("https://api.example.com");

  return (
    <div>
      <header>
        <h1>Dashboard</h1>
      </header>
      <p>Widgets load their data from api.example.com once mounted.</p>
    </div>
  );
}

Escalating from a connection hint to a real fetch

The connection hint fires once for the whole list, at a point where only the host is known. When the user hovers a specific card the exact poster URL exists, so the code escalates to a download hint that reuses the already-open connection. This ordering — host first, URL when known — is the intended division of labour between the two APIs.

Example · jsx
import { useState } from "react";
import { preconnect, preload } from "react-dom";

function VideoCard({ video, onPlay }) {
  return (
    <li>
      <button
        onMouseEnter={() => {
          // Now the URL is known, so start the transfer.
          preload(video.posterUrl, { as: "image" });
        }}
        onClick={() => onPlay(video.id)}
      >
        {video.title}
      </button>
    </li>
  );
}

export default function VideoList() {
  const [playing, setPlaying] = useState("none");

  // Before any titles have loaded, we only know the host.
  preconnect("https://media.example-cdn.com");

  const videos = [
    { id: "a1", title: "Intro", posterUrl: "https://media.example-cdn.com/a1.jpg" },
    { id: "b2", title: "Deep dive", posterUrl: "https://media.example-cdn.com/b2.jpg" },
  ];

  return (
    <div>
      <p>Playing: {playing}</p>
      <ul>
        {videos.map((video) => (
          <VideoCard key={video.id} video={video} onPlay={setPlaying} />
        ))}
      </ul>
    </div>
  );
}

Discussion

  • Be the first to comment on this lesson.