DriversRecommendedOutdated drivers can make a good PC feel brokenScan driver issues before chasing fixes manually.Scan NowHalloween DealsAmazon USHalloween week deals: useful picks before month-endAmazon US: current deals, useful picks and tech finds.Check DealsWindows FixRecommendedWindows errors stealing your time? Find the fix fastScan stability, cleanup and performance issues.Fix Now×
FREEDOM251

Freedom251 › Blog › JavaScript

How to use React’s browser() API for client-only rendering

By Freedom251 Team · · 10 min read

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use React DOM’s browser() together with React’s use() and a surrounding <Suspense> boundary. The server renders the boundary’s fallback, while the browser lets the component continue and read browser-only values such as localStorage or the device time zone.

The short answer

Import use from react and browser from react-dom. Inside the component that cannot produce useful server HTML, call use(browser('A concise reason')). Render that component beneath <Suspense fallback={...}>.

As an Amazon Associate I earn from qualifying purchases.

import { Suspense, use, useState } from 'react';
import { browser } from 'react-dom';

function SavedDraft() {
  use(browser('The draft is stored in localStorage.'));

  const [draft, setDraft] = useState(
    () => localStorage.getItem('draft') ?? ''
  );

  function handleChange(event) {
    const nextDraft = event.target.value;
    setDraft(nextDraft);
    localStorage.setItem('draft', nextDraft);
  }

  return (
    <label>
      Draft:
      <textarea value={draft} onChange={handleChange} rows={4} cols={30} />
    </label>
  );
}

export default function App() {
  return (
    <Suspense fallback={<p>Loading draft...</p>}>
      <SavedDraft />
    </Suspense>
  );
}

During server rendering, use(browser()) suspends SavedDraft, so the nearest Suspense fallback is emitted in the initial HTML. During the browser render, the same call returns undefined, and the component proceeds normally. After hydration, the user sees the value from localStorage.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

What browser() actually does

browser(reason?) is a React DOM API that returns an opaque value. The value has meaning only when passed to React’s use() during component rendering. That combination marks the current component as browser-only for server rendering.

#1 Best Overall
Sale
TOZO A1 Wireless Earbuds Bluetooth 5.3 Light Weight in Ear Headphones | IPX5 Waterproof,2 Mics for AI Calls,Immersive Premium Sound Bass Headset with Charging Case,32 EQ via App Black
  • [Ultra-Lightweight Ear Buds Designed for Small Ears] Each earbud weighs only 3.7g and features a compact, ergonomic in-ear design made especially for small ears. Secure, low-profile, and comfortable for workouts, all-day wear or overnight sleeping.The ultra-slim profile sits flush in your ear with no hard edges poking or rubbing, so you can even sleep on your side without discomfort.
  • [Immersive Stereo Sound with TOZO OrigX Technology] TOZO OrigX tuning delivers clear vocals, balanced mids, and natural stereo sound for music, podcasts, and videos.
  • [Long Battery Life for Daily Use] Get up to 7 hours of playtime on a single charge, with up to 32 hours total using the charging case—ideal for workdays, commuting, and extended listening sessions.
  • [Bluetooth 5.3 & Stable Connection] Bluetooth 5.3 provides fast pairing, stable wireless performance, and reduced dropouts as you move around home or office.
  • [Deep Bass with Clear Vocals] High-performance drivers produce punchy bass while keeping vocals clean and detailed for everyday listening.
  • Calling browser() by itself has no effect.
  • Do not throw the value returned by browser().
  • The component-level call causes React to leave the component on the server and use the closest Suspense fallback.
  • In the browser, use(browser()) returns undefined; it is not a promise and does not provide a browser object.

React documents this API for cases where the server cannot produce meaningful UI. Typical examples include data in localStorage, the user’s local time zone, viewport-dependent values, or other state that exists only after JavaScript starts in a browser.

This is different from a general client-rendering switch. The surrounding page can remain server-rendered; only the component containing the call opts out. Keep headings, explanatory text, navigation, and other stable content outside the boundary whenever they can be rendered on the server.

Build the pattern step by step

1. Put the browser-only read in its own component

Keep browser globals out of module scope and out of code that the server must execute. Put the read in the component that needs it, after the use(browser()) call. In the example, the lazy initializer for useState runs only after the component is rendering in the browser, so localStorage is available.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

2. Pass a useful reason

The optional argument can be a string or a function. A concise reason helps server-renderer diagnostics identify why the component is browser-only. React uses that value as the bailout error’s cause; it does not serialize the reason into the HTML. If the reason is a function, React evaluates it on the server when the call is encountered, not in the browser.

3. Add the nearest Suspense boundary

Wrap the component with <Suspense fallback={...}> during server rendering. The fallback should be valid, useful initial HTML rather than a blank area whenever possible. It can contain a loading message, a skeleton with an accessible label, or a server-known placeholder that does not pretend to be the final browser value.

4. Render the boundary from a server-capable parent

The parent may remain a Server Component or another server-rendered component. The boundary controls the initial output, while the child takes over in the browser. This lets the rest of the route retain server rendering, streaming, and crawlable content.

5. Confirm the browser-only path after hydration

In development, verify that the server response contains the fallback and that the hydrated page replaces it with the component. Test with an empty storage key, an existing key, disabled storage, and a browser with JavaScript disabled. The fallback is the only representation available in the initial HTML for this component.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Why Suspense is mandatory

A browser bailout is implemented through suspension. React needs a boundary that can receive the suspended subtree and render something in its place. Without a boundary that covers the call, server rendering fails instead of producing a controlled fallback.

Rank #2
Sale
Smart Watch for Men Women Compatible with iPhone Samsung Android Phone 1.69 inch Full Touch Screen IP68 Waterproof Bluetooh Fitness Tracker Heart Rate/Sleep Monitor (Black)
  • 【IP68 Waterproof Multifunctinal Smart Watch】Torjalph fitness activity tracker smart watch is IP68 waterproof technology ,you can wear it when swimming,handwashing,it's rain-proof which means that you perform multiple exercise modes outside without worrying about sweat or rain corroding your fitness smart watch,and this watch equipped with a 230 mAh large capacity battery magnetic charging ,and this sports activity tracker watch can be used 5-7 days If fully charged.
  • 【Larger 1.83'' Full Screen Watch & Multi-dial Selection】1.83 inch full HD color touch screen smart watch for men / women provides excellent 240*284 resolution image quality ,This Bluetooth smart watch offers a better touch experience and remarkable immersion and ,more than 200 watch faces for you to choose from App"Da Fit ", you can change the dial style according to your mood to wear keeping the world on your wrist
  • 【Accurate Activity Tracker Smart Watch 】sports watch activity tracker uses sweat and dust resistant breathable silicone strap, our Fitness Tracker Smart Watch for Android iOS Phones supports 12 sports modes,walking,running,bicycle,swimming,badminton,basketball,football,rope skipping. This bluetooth calls smart watch for men women is lightweight and stylish, bringing more convenient and relaxing sports experience while also providing more protection.
  • 【Your 24 Hour Personal Daily Health Monitor】Fitness watch for women men full touch screen IP67 waterproof bluetooth smartwatch for Android iOS Phones with heart rate blood pressure monitor multifunction Andriod smart watch with steps counter sleep monitor sports fitness watch, monitoring blood oxygen saturation allows you to understand your physical condition in real time to track fitness progress ,to know your health status in time.
  • 【More Functions Bluetooth Call Smart Watch】This fitness activity smart watch full screen for iPhone and Android phones includes a bunch of new features including:The bluetooth smart watch can hang up the phone, receive and display WhatsAPP /Text /Facebook /Twitter /Messenger reminder.Support sedentary reminder, alarm clock, stopwatch, timer,weather information,music control, remote camera control compatible with Android 5.0 and above or iOS 9.0 and above smartphones.

The boundary’s fallback is part of the initial server response. When the browser hydrates the page, React retries the suspended subtree in the browser, where use(browser()) returns undefined. The component then executes its normal render logic.

Place the boundary as close as practical to the browser-only component. A boundary higher in the tree can technically handle the suspension, but it may replace a much larger section of the page than intended. Nest boundaries when different regions need independent loading states.

Client Components and React Server Components

In an application using React Server Components, the call to use(browser()) must be in a Client Component. Add the client directive at the top of the module that contains the call:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
'use client';

import { use, useState } from 'react';
import { browser } from 'react-dom';

export function LocalDraft() {
  use(browser('This component reads localStorage.'));
  const [value, setValue] = useState(
    () => localStorage.getItem('draft') ?? ''
  );
  return <textarea value={value} onChange={event => setValue(event.target.value)} />;
}

Alternatively, leave the parent as a Server Component and move the call into a child module marked 'use client'. The directive defines a boundary in the module dependency tree: the marked module and the code it imports for that client entry are treated as client code. It does not turn the entire application into client-side rendering.

Follow your framework’s rules for where Client Components may be imported and where Suspense boundaries are placed. React’s Client Component documentation explains the module boundary; framework documentation determines routing, streaming, and build integration.

Conditional use: render on the server when you have enough data

React permits use(browser()) inside a condition or after an early return. This is useful when a component can render meaningful server HTML if a prop is supplied, but must wait for the browser when that prop is absent.

import { use } from 'react';
import { browser } from 'react-dom';

function LocalTime({ timeZone }) {
  if (timeZone) {
    return <time>Showing time for {timeZone}</time>;
  }

  use(browser('The device time zone is available only in the browser.'));
  const deviceTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
  return <time>Showing time for {deviceTimeZone}</time>;
}

This conditional form is a data decision, not a workaround for the Rules of Hooks. React specifically allows use to be called conditionally. If the server has an initial value, use it and preserve useful HTML. If the value exists only on the device, suspend deliberately and provide a truthful fallback.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The same choice applies to server data. When initial data is present, render it on the server. When it is missing and a browser-only source is the only meaningful source, use the browser bailout rather than making the server issue a query that cannot produce the desired result.

Rank #3
New Bee Guitar Cable 10ft Electric Instrument Bass AMP Cord | 6.35mm Jack, Durable Design, Stage and Home Studio Use, Low Noise Shielded Electric Cord for Bass, Keyboard, Amp, Mixer
  • [Low Noise High Fidelity] New bee guitar cord with 22AWG oxygen-free-copper center conductors provides enhanced signal transfer, the PVC insulation material and the high-density stranded copper double shield provide noise rejection for quiet operation
  • [Ideal for Choice] New bee 1/4 straight and right angle metal connectors, ensures a secure connection in any instrument, pedal, or amp jack. L shape great fro on stage guitar stands
  • [Wide Compatible] Suitable for mixer, power amplifier, microphone, effector, decoder, equalizer, electoronic organ, electric guitar, electric bass and other electronic equipments. Widely used in the installation of smart home, karaoke speaker, professional stage audio, etc
  • [Easy Disassemble] Making incidental repairs quick and easy! Very nice, flexible cable
  • [Dont Hesite to Order] 24 hours customer services and professional technology team are standing by

Choosing between browser-only techniques

Approach Initial HTML Use it when Main trade-off
use(browser()) inside <Suspense> The nearest fallback The component genuinely cannot render meaningful UI on the server The browser-only content is absent from the initial response
Server-render a default or initial value Useful content based on supplied data A prop, cookie, request value, or other server input is good enough The initial value may differ from the eventual device value
Mounted state with an Effect Usually a server-safe placeholder, then a client update Your existing component already uses an explicit mounted-state flow It adds an extra client transition and must be designed to avoid mismatches
typeof window branching Whatever the server branch returns A small branch can safely produce equivalent markup It is easy to create mismatched markup or scatter environment checks
Framework server-rendering opt-out Framework-defined client loading output The framework supplies a supported route-level or component-level switch Configuration and behavior differ by framework

React presents these as alternatives rather than interchangeable guarantees. Choose the smallest scope that solves the problem. If a server-known default is acceptable, it generally gives users more useful initial HTML than opting out of rendering the whole component.

Fallback design for users, accessibility, and crawlers

The fallback is not merely an internal loading flag. It is what users and crawlers receive in the initial server HTML for the browser-only region.

  • Describe what is unavailable without implying that the final value is already known.
  • Keep the fallback’s structure stable so replacing it does not cause a distracting layout shift.
  • Use semantic elements and accessible text; a decorative spinner alone does not explain the state.
  • Place important explanatory copy, labels, and navigation outside the boundary when they should be present without JavaScript.
  • Do not put a device-specific result in the fallback unless the server actually knows it.

For a saved draft, “Loading draft…” is accurate while storage is being read. For a local-time display, a server-provided time zone or a neutral “Your local time will appear here” message avoids claiming a value the server cannot determine.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Browser bailout reporting versus ordinary errors

Server renderers can receive an onBrowserBailout callback. When React switches a subtree to its Suspense fallback for browser rendering, the callback receives an Error describing the browser-only render and an errorInfo object containing the component stack.

This callback is intentionally separate from ordinary render-error reporting:

  • A browser bailout does not call the server renderer’s onError.
  • It does not call hydrateRoot’s onRecoverableError.
  • If no Suspense boundary can handle the bailout, server rendering fails through the usual error path.

Use onBrowserBailout for observability of expected browser-only regions, not as a replacement for exception handling. An actual exception thrown while rendering the component in the browser remains an ordinary application error and needs the normal client-side error strategy.

Advanced streaming: aborting a pending server render

Direct server-rendering APIs can pass browser(reason) to abort when stopping a pending render. React keeps pending Suspense boundaries on their fallbacks so those regions can finish in the browser.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

When an API accepts an AbortSignal, pass the value as the abort reason:

Rank #4
BSIMB 15.6" Digital Family Calendar & Chore Chart, No Subscription Fees
  • Digital Family Calendar: BSIMB digital calendar wall touch screen puts an end to your chaotic life. Designed for busy families, the digital calendar keeps you organised and in step with your family. Assign different colours and tasks to each family member to make family scheduling easier and more intuitive.
  • Easy Setup and Auto-Sync: Plug in, connect to WLAN and auto-syn your electric calendar in minutes. Digital wall calendar compatible with Google calendar, iCloud calendar, Outlook calendar, Cozi calendar and Yahoo calendar. Add events directly on the device or through the ecalendar app. Electronic calendar stays current whether you're at work or traveling—no manual updates needed.
  • All-In-One Home Assistant: Smart calendar builds habits and encourage independence with personalised chores. Display daily meal plan to reduce the daily ‘What's for dinner?’ stress. To-do lists keep track of everything you want. Turning chores into valuable achievements with stars and rewards, making life easier and more enjoyable.
  • Manage Anytime Anywhere: BSIMB electronic calendar for family stay connected with the powerful ecalendar app. Access and manage your digital wall calendar anytime, anywhere with free features like stars & rewards, photo screensaver, chore charts, meals plans, to-do lists etc. Electronic planner paid features like Magic Import tailor advanced tools for users with special needs.
  • Stay in Touch with Loved Ones: Share photos or videos from your phone to electronic wall calendar with app, instantly update your life moment, and keep in touch with your family, especially those who are far away; you can also surprise your smart calendar digital wall by sending him a wish card; it's also great for keeping tech-illiterate elders in touch with the youngsters.
controller.abort(browser('Finish the remaining regions in the browser.'));

This is an advanced streaming technique. Framework applications should use the framework’s documented server-rendering integration instead of reaching for a renderer-level abort unless they own that integration.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Common mistakes and fixes

Calling browser() without use()

Symptom: Nothing changes on the server, and browser globals still run too early.

Fix: Call use(browser(reason)) during component rendering. The standalone function call is intentionally inert.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Throwing the returned value

Symptom: The component enters an error path instead of the documented browser-only flow.

Fix: Never throw the opaque value. Pass it directly to use().

Omitting Suspense

Symptom: Server rendering fails because no boundary can receive the suspension.

Fix: Put the component under a server-rendered <Suspense fallback={...}>. Verify that the boundary actually encloses the component in the rendered tree.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Reading browser globals before the bailout

Symptom: A server error such as an undefined localStorage occurs before React can switch to the fallback.

Fix: Keep browser-only reads after use(browser()), inside browser-executed code such as a lazy state initializer or event handler. Do not read them at module scope.

Using the call in a Server Component

Symptom: A React Server Components build rejects the module or treats the code as server-only.

Fix: Add 'use client' to the module containing the call, or move the call into a child Client Component.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Making the fallback the entire page

Symptom: The response contains only a generic loading screen even though most of the page is server-renderable.

Fix: Narrow the boundary to the component that truly needs browser execution and keep stable surrounding content outside it.

Assuming the reason appears in HTML

Symptom: Instrumentation or client code expects the reason string to be available in the response.

Fix: Treat the reason as server-side diagnostic information. React uses it as the bailout error’s cause; it is not serialized into HTML.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Release-channel and framework support

Check the React version and release channel installed in the project before deploying this API. The current English React API reference documents browser() but does not state a minimum stable version or a release-channel requirement. A React release article dated 9 September 2026 discusses the server-fallback behavior in the context of React 19.3, while a localized documentation page labels the API Canary; those facts do not by themselves establish that every framework or stable installation exposes the same API.

Confirm all of the following in the project’s own dependency and framework documentation:

  • The installed react and react-dom versions expose browser.
  • The selected release channel permits the API in production.
  • The framework’s server renderer supports the Suspense and streaming behavior required by the component.
  • React Server Components boundaries are configured so the call is compiled as client code when needed.
  • Your deployment’s hydration and error-reporting hooks handle browser bailouts as documented.

Do not infer support from a different React version, a framework option, or a translated page alone. Test the exact dependency lockfile and deployment configuration you intend to ship.

A practical implementation checklist

  1. Identify the smallest component whose UI depends on browser-only state.
  2. Import use from react and browser from react-dom.
  3. Call use(browser('brief reason')) at the point where the component must switch to browser rendering.
  4. Read localStorage, browser APIs, or device settings only after that call.
  5. Wrap the component in the nearest meaningful <Suspense fallback={...}>.
  6. If using React Server Components, mark the module 'use client' or move the call into a Client Component child.
  7. Make the fallback useful, accessible, and honest about what the server does not know.
  8. Test the server HTML, hydration, empty and populated browser state, and JavaScript-disabled behavior.
  9. Wire server diagnostics to onBrowserBailout when you need visibility into expected bailouts.
  10. Verify the installed React release channel and framework integration before production rollout.

What to remember

browser() is a targeted server-rendering bailout, not a standalone directive and not a command to throw. The essential pattern is use(browser()) inside the component, covered by Suspense. The server sends the nearest fallback; the browser runs the component normally. Keep the boundary narrow, use a Client Component in React Server Components applications, and choose a server-rendered default instead whenever the server already has enough information to produce useful HTML.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

JavaScriptReactReact DOMReact Server ComponentsServer renderingSuspense

Leave a Reply

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

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Recommended PC Tool
Recommended PC Tool
Windows Errors? Fix Them Before They SpreadFree repair scan
Crashes, No Sound, or Screen Glitches?Free driver scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.