- Spec files
npm-react
Describes: pkg:npm/react@18.3.x
- Description
- React is a JavaScript library for building user interfaces with declarative, component-based architecture.
- Author
- tessl
- Last updated
hooks.md docs/
1# React Hooks23React Hooks provide a way to use state and lifecycle features in function components. They enable stateful logic reuse and eliminate the need for class components in most cases.45## Capabilities67### State Hooks89#### useState1011Adds state to function components with getter and setter.1213```javascript { .api }14/**15* Returns stateful value and function to update it16* @param initialState - Initial state value or function that returns initial state17* @returns Tuple with current state and state setter function18*/19function useState<S>(initialState: S | (() => S)): [S, Dispatch<SetStateAction<S>>];2021// State setter type22type Dispatch<A> = (value: A) => void;23type SetStateAction<S> = S | ((prevState: S) => S);24```2526**Usage Examples:**2728```javascript29import { useState } from 'react';3031// Basic usage32const [count, setCount] = useState(0);33const [user, setUser] = useState({ name: 'John', age: 30 });3435// Functional updates36setCount(prevCount => prevCount + 1);37setUser(prevUser => ({ ...prevUser, age: prevUser.age + 1 }));3839// Lazy initial state40const [expensiveValue, setExpensiveValue] = useState(() => {41return computeExpensiveValue();42});43```4445#### useReducer4647Manages complex state with reducer pattern, alternative to useState for complex state logic.4849```javascript { .api }50/**51* State management with reducer pattern52* @param reducer - Function that determines state updates53* @param initialArg - Initial state or value for lazy initialization54* @param init - Optional lazy initialization function55* @returns Tuple with current state and dispatch function56*/57function useReducer<R extends Reducer<any, any>>(58reducer: R,59initialArg: ReducerState<R>,60init?: ReducerStateWithoutAction<R>61): [ReducerState<R>, Dispatch<ReducerAction<R>>];6263// Reducer types64type Reducer<S, A> = (prevState: S, action: A) => S;65type ReducerState<R extends Reducer<any, any>> = R extends Reducer<infer S, any> ? S : never;66type ReducerAction<R extends Reducer<any, any>> = R extends Reducer<any, infer A> ? A : never;67```6869**Usage Examples:**7071```javascript72import { useReducer } from 'react';7374// Counter reducer75function counterReducer(state, action) {76switch (action.type) {77case 'increment':78return { count: state.count + 1 };79case 'decrement':80return { count: state.count - 1 };81case 'set':82return { count: action.payload };83default:84throw new Error();85}86}8788const [state, dispatch] = useReducer(counterReducer, { count: 0 });8990// Dispatch actions91dispatch({ type: 'increment' });92dispatch({ type: 'set', payload: 42 });93```9495### Effect Hooks9697#### useEffect9899Performs side effects in function components - equivalent to componentDidMount, componentDidUpdate, and componentWillUnmount combined.100101```javascript { .api }102/**103* Performs side effects after render104* @param effect - Function containing side effect logic105* @param deps - Optional dependency array to control when effect runs106*/107function useEffect(effect: EffectCallback, deps?: DependencyList): void;108109type EffectCallback = () => (void | Destructor);110type Destructor = () => void | { [UNDEFINED_VOID_ONLY]: never };111type DependencyList = ReadonlyArray<any>;112```113114**Usage Examples:**115116```javascript117import { useEffect, useState } from 'react';118119function UserProfile({ userId }) {120const [user, setUser] = useState(null);121122// Effect with dependencies123useEffect(() => {124fetchUser(userId).then(setUser);125}, [userId]);126127// Effect with cleanup128useEffect(() => {129const timer = setInterval(() => {130console.log('Timer tick');131}, 1000);132133return () => clearInterval(timer);134}, []);135136// Effect on every render (no deps array)137useEffect(() => {138console.log('Component rendered');139});140}141```142143#### useLayoutEffect144145Synchronous version of useEffect that fires before browser paints, useful for DOM measurements.146147```javascript { .api }148/**149* Synchronous side effects that fire before browser paint150* @param effect - Function containing side effect logic151* @param deps - Optional dependency array to control when effect runs152*/153function useLayoutEffect(effect: EffectCallback, deps?: DependencyList): void;154```155156**Usage Examples:**157158```javascript159import { useLayoutEffect, useRef } from 'react';160161function MeasuredComponent() {162const ref = useRef();163164useLayoutEffect(() => {165// Synchronously measure DOM before paint166const rect = ref.current.getBoundingClientRect();167console.log('Element height:', rect.height);168});169170return <div ref={ref}>Content</div>;171}172```173174#### useInsertionEffect175176Special effect hook for CSS-in-JS libraries to insert styles before layout effects.177178```javascript { .api }179/**180* Effect hook for CSS-in-JS libraries to insert styles181* @param effect - Function containing style insertion logic182* @param deps - Optional dependency array to control when effect runs183*/184function useInsertionEffect(effect: EffectCallback, deps?: DependencyList): void;185```186187### Performance Hooks188189#### useMemo190191Memoizes expensive computations to avoid recalculation on every render.192193```javascript { .api }194/**195* Memoizes expensive calculations196* @param factory - Function that returns value to memoize197* @param deps - Dependency array to determine when to recalculate198* @returns Memoized value199*/200function useMemo<T>(factory: () => T, deps: DependencyList): T;201```202203**Usage Examples:**204205```javascript206import { useMemo, useState } from 'react';207208function ExpensiveComponent({ items, query }) {209const filteredItems = useMemo(() => {210return items.filter(item =>211item.name.toLowerCase().includes(query.toLowerCase())212);213}, [items, query]);214215const expensiveValue = useMemo(() => {216return computeExpensiveValue(items);217}, [items]);218219return <div>{/* render filtered items */}</div>;220}221```222223#### useCallback224225Memoizes functions to prevent unnecessary re-renders of child components.226227```javascript { .api }228/**229* Memoizes callback functions230* @param callback - Function to memoize231* @param deps - Dependency array to determine when to recreate function232* @returns Memoized callback function233*/234function useCallback<T extends Function>(callback: T, deps: DependencyList): T;235```236237**Usage Examples:**238239```javascript240import { useCallback, useState } from 'react';241242function ParentComponent({ onItemClick }) {243const [count, setCount] = useState(0);244const [items, setItems] = useState([]);245246const handleClick = useCallback((id) => {247onItemClick(id);248setCount(prev => prev + 1);249}, [onItemClick]);250251const addItem = useCallback(() => {252setItems(prev => [...prev, { id: Date.now() }]);253}, []);254255return (256<div>257<ItemList items={items} onItemClick={handleClick} />258<button onClick={addItem}>Add Item</button>259</div>260);261}262```263264### Ref Hooks265266#### useRef267268Creates mutable ref object that persists across re-renders.269270```javascript { .api }271/**272* Creates mutable ref object273* @param initialValue - Initial value for the ref274* @returns Mutable ref object with current property275*/276function useRef<T>(initialValue: T): MutableRefObject<T>;277function useRef<T>(initialValue: T | null): RefObject<T>;278function useRef<T = undefined>(): MutableRefObject<T | undefined>;279280interface MutableRefObject<T> {281current: T;282}283```284285**Usage Examples:**286287```javascript288import { useRef, useEffect } from 'react';289290function InputComponent() {291const inputRef = useRef(null);292const countRef = useRef(0);293294useEffect(() => {295// Focus input on mount296inputRef.current.focus();297}, []);298299const handleClick = () => {300// Mutable value that doesn't trigger re-render301countRef.current += 1;302console.log('Click count:', countRef.current);303};304305return (306<div>307<input ref={inputRef} />308<button onClick={handleClick}>Click me</button>309</div>310);311}312```313314#### useImperativeHandle315316Customizes the instance value exposed when using ref with forwardRef.317318```javascript { .api }319/**320* Customizes ref handle for forwardRef components321* @param ref - Ref object to customize322* @param createHandle - Function that returns the custom handle323* @param deps - Optional dependency array324*/325function useImperativeHandle<T, R extends T>(326ref: Ref<T> | undefined,327init: () => R,328deps?: DependencyList329): void;330```331332**Usage Examples:**333334```javascript335import { forwardRef, useImperativeHandle, useRef } from 'react';336337const CustomInput = forwardRef((props, ref) => {338const inputRef = useRef();339340useImperativeHandle(ref, () => ({341focus: () => inputRef.current.focus(),342blur: () => inputRef.current.blur(),343getValue: () => inputRef.current.value,344}), []);345346return <input ref={inputRef} {...props} />;347});348349// Usage350function ParentComponent() {351const customInputRef = useRef();352353const handleClick = () => {354customInputRef.current.focus();355console.log(customInputRef.current.getValue());356};357358return (359<div>360<CustomInput ref={customInputRef} />361<button onClick={handleClick}>Focus Input</button>362</div>363);364}365```366367### Context Hooks368369#### useContext370371Consumes context values from React context providers.372373```javascript { .api }374/**375* Consumes context value from nearest provider376* @param context - Context object created by createContext377* @returns Current context value378*/379function useContext<T>(context: Context<T>): T;380```381382**Usage Examples:**383384```javascript385import { createContext, useContext } from 'react';386387const ThemeContext = createContext('light');388const UserContext = createContext(null);389390function ThemedButton() {391const theme = useContext(ThemeContext);392const user = useContext(UserContext);393394return (395<button className={`btn-${theme}`}>396Hello, {user?.name || 'Guest'}397</button>398);399}400401function App() {402const user = { name: 'John', id: 1 };403404return (405<ThemeContext.Provider value="dark">406<UserContext.Provider value={user}>407<ThemedButton />408</UserContext.Provider>409</ThemeContext.Provider>410);411}412```413414### Concurrent Features Hooks415416#### useTransition417418Marks state updates as non-urgent transitions to avoid blocking urgent updates.419420```javascript { .api }421/**422* Marks state updates as non-urgent transitions423* @returns Tuple with isPending boolean and startTransition function424*/425function useTransition(): [boolean, (callback: () => void) => void];426```427428**Usage Examples:**429430```javascript431import { useTransition, useState } from 'react';432433function SearchComponent() {434const [query, setQuery] = useState('');435const [results, setResults] = useState([]);436const [isPending, startTransition] = useTransition();437438const handleSearch = (newQuery) => {439setQuery(newQuery); // Urgent update440441startTransition(() => {442// Non-urgent update that won't block typing443setResults(performExpensiveSearch(newQuery));444});445};446447return (448<div>449<input450value={query}451onChange={(e) => handleSearch(e.target.value)}452/>453{isPending && <div>Searching...</div>}454<ResultsList results={results} />455</div>456);457}458```459460#### useDeferredValue461462Defers updating a value to avoid blocking urgent updates.463464```javascript { .api }465/**466* Defers value updates for performance467* @param value - Value to defer468* @returns Deferred version of the value469*/470function useDeferredValue<T>(value: T): T;471```472473**Usage Examples:**474475```javascript476import { useDeferredValue, useState, useMemo } from 'react';477478function ProductList({ products }) {479const [filter, setFilter] = useState('');480const deferredFilter = useDeferredValue(filter);481482const filteredProducts = useMemo(() => {483return products.filter(product =>484product.name.includes(deferredFilter)485);486}, [products, deferredFilter]);487488return (489<div>490<input491value={filter}492onChange={(e) => setFilter(e.target.value)}493placeholder="Filter products..."494/>495<div>496{filteredProducts.map(product => (497<ProductCard key={product.id} product={product} />498))}499</div>500</div>501);502}503```504505### Utility Hooks506507#### useId508509Generates stable unique IDs for accessibility attributes.510511```javascript { .api }512/**513* Generates unique IDs for accessibility514* @returns Stable unique ID string515*/516function useId(): string;517```518519**Usage Examples:**520521```javascript522import { useId } from 'react';523524function FormField({ label, ...props }) {525const id = useId();526527return (528<div>529<label htmlFor={id}>{label}</label>530<input id={id} {...props} />531</div>532);533}534535function LoginForm() {536const passwordHintId = useId();537538return (539<form>540<FormField label="Username" type="text" />541<FormField542label="Password"543type="password"544aria-describedby={passwordHintId}545/>546<div id={passwordHintId}>547Password must be at least 8 characters548</div>549</form>550);551}552```553554#### useDebugValue555556Displays custom labels for custom hooks in React DevTools.557558```javascript { .api }559/**560* Displays debug labels in React DevTools561* @param value - Value to display562* @param format - Optional formatting function563*/564function useDebugValue<T>(value: T, format?: (value: T) => any): void;565```566567**Usage Examples:**568569```javascript570import { useDebugValue, useState, useEffect } from 'react';571572function useOnlineStatus() {573const [isOnline, setIsOnline] = useState(navigator.onLine);574575useEffect(() => {576const handleOnline = () => setIsOnline(true);577const handleOffline = () => setIsOnline(false);578579window.addEventListener('online', handleOnline);580window.addEventListener('offline', handleOffline);581582return () => {583window.removeEventListener('online', handleOnline);584window.removeEventListener('offline', handleOffline);585};586}, []);587588// Show in DevTools589useDebugValue(isOnline ? 'Online' : 'Offline');590591return isOnline;592}593594function useLocalStorage(key, initialValue) {595const [storedValue, setStoredValue] = useState(() => {596try {597const item = window.localStorage.getItem(key);598return item ? JSON.parse(item) : initialValue;599} catch (error) {600return initialValue;601}602});603604// Custom format function605useDebugValue({key, storedValue}, ({key, storedValue}) =>606`${key}: ${JSON.stringify(storedValue)}`607);608609return [storedValue, setStoredValue];610}611```612613### External Store Hooks614615#### useSyncExternalStore616617Subscribes to external data stores and syncs with React's rendering.618619```javascript { .api }620/**621* Subscribes to external data stores622* @param subscribe - Function to subscribe to store changes623* @param getSnapshot - Function to get current store value624* @param getServerSnapshot - Optional server-side snapshot getter625* @returns Current store value626*/627function useSyncExternalStore<Snapshot>(628subscribe: (onStoreChange: () => void) => () => void,629getSnapshot: () => Snapshot,630getServerSnapshot?: () => Snapshot631): Snapshot;632```633634**Usage Examples:**635636```javascript637import { useSyncExternalStore } from 'react';638639// External store example640const store = {641state: { count: 0 },642listeners: new Set(),643644getState() {645return this.state;646},647648setState(newState) {649this.state = { ...this.state, ...newState };650this.listeners.forEach(listener => listener());651},652653subscribe(listener) {654this.listeners.add(listener);655return () => this.listeners.delete(listener);656}657};658659function useStore() {660return useSyncExternalStore(661store.subscribe.bind(store),662store.getState.bind(store)663);664}665666function Counter() {667const state = useStore();668669return (670<div>671<p>Count: {state.count}</p>672<button onClick={() => store.setState({ count: state.count + 1 })}>673Increment674</button>675</div>676);677}678```679680#### useMutableSource681682Legacy hook for subscribing to mutable external sources (deprecated in favor of useSyncExternalStore).683684```javascript { .api }685/**686* Subscribe to mutable external data sources (deprecated)687* @param source - Mutable source created by createMutableSource688* @param getSnapshot - Function to get current value from source689* @param subscribe - Function to subscribe to source changes690* @returns Current source value691*/692function useMutableSource<Source, Snapshot>(693source: MutableSource<Source>,694getSnapshot: MutableSourceGetSnapshotFn<Source, Snapshot>,695subscribe: MutableSourceSubscribeFn<Source, Snapshot>696): Snapshot;697```