Skip to content

Docs · Framework

React

React 19 features the components rely on.

Components are written for React 19.3 with the React Compiler on. They use a handful of React 19 APIs that older tutorials won't show.

Install

create-next-app installs React for you. By hand, pin the same version for both packages and add the types:

pnpm add react@19.3.1 react-dom@19.3.1
pnpm add -D @types/react @types/react-dom

React 19 APIs the components use

Context as provider, and use()

toast.tsx
import { createContext, use } from "react"; const ToastContext = createContext<((t: ToastOptions) => void) | null>(null); // <Context> is the provider now; no .Provider<ToastContext value={show}>{children}</ToastContext> // use() reads context, and can be called after an early returnexport function useToast() {  const show = use(ToastContext);  if (!show) throw new Error("useToast must be used inside <ToastProvider>");  return show;}

ref as a prop

beam.tsx
// ref is a normal prop: no forwardRefexport function BeamNode({ ref, icon, label }: { ref?: Ref<HTMLDivElement> /* … */ }) {  return <div ref={ref}>{/* … */}</div>;}

useEffectEvent

For callbacks an effect calls but shouldn't restart for. The toast timer uses it so a new onDismiss doesn't reset the countdown.

toast.tsx
const close = useEffectEvent(onDismiss); useEffect(() => {  if (paused) return;  const timer = setTimeout(close, remaining); // always calls the latest onDismiss  return () => clearTimeout(timer);}, [paused]); // onDismiss isn't a dependency, so the timer doesn't restart

useSyncExternalStore

For values that live outside React, such as localStorage or a media query. The theme, custom theme and package-manager tabs on this site all use it.

theme-provider.tsx
// Read browser state without a flash of the wrong value after hydrationconst theme = useSyncExternalStore(  subscribe,               // listen for changes  () => localStorage.getItem("theme") ?? "system", // value in the browser  () => "system",          // value during server render);

React Compiler

The compiler memoizes components and values automatically, so you rarely need useMemo, useCallback or memo. Turn it on with reactCompiler: true in next.config.ts and the babel-plugin-react-compiler dev dependency; see Next.js.

It relies on the rules of React: no mutating props or state, and hooks only at the top level. Learn more at react.dev.