You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
React 19 patterns with React Compiler. Trigger: When writing React 19 components/hooks in .tsx (React Compiler rules, hook patterns, refs as props). If using Next.js App Router/Server Actions, also use nextjs-16.
// ✅ ALWAYS: Named importsimport{useState,useEffect,useRef}from"react";// ❌ NEVERimportReactfrom"react";import*asReactfrom"react";
Server Components First
// ✅ Server Component (default) - no directiveexportdefaultasyncfunctionPage(){constdata=awaitfetchData();return<ClientComponentdata={data}/>;}// ✅ Client Component - only when needed"use client";exportfunctionInteractive(){const[state,setState]=useState(false);return<buttononClick={()=>setState(!state)}>Toggle</button>;}
When to use "use client"
useState, useEffect, useRef, useContext
Event handlers (onClick, onChange)
Browser APIs (window, localStorage)
use() Hook
import{use}from"react";// Read promises (suspends until resolved)functionComments({ promise }){constcomments=use(promise);returncomments.map(c=><divkey={c.id}>{c.text}</div>);}// Conditional context (not possible with useContext!)functionTheme({ showTheme }){if(showTheme){consttheme=use(ThemeContext);return<divstyle={{color: theme.primary}}>Themed</div>;}return<div>Plain</div>;}
Actions & useActionState
"use server";asyncfunctionsubmitForm(formData: FormData){awaitsaveToDatabase(formData);revalidatePath("/");}// With pending stateimport{useActionState}from"react";functionForm(){const[state,action,isPending]=useActionState(submitForm,null);return(<formaction={action}><buttondisabled={isPending}>{isPending ? "Saving..." : "Save"}</button></form>);}
ref as Prop (No forwardRef)
// ✅ React 19: ref is just a propfunctionInput({ ref, ...props}){return<inputref={ref}{...props}/>;}// ❌ Old way (unnecessary now)constInput=forwardRef((props,ref)=><inputref={ref}{...props}/>);