# React React is a JavaScript library for building user interfaces through a declarative, component-based approach. It enables developers to create interactive web applications by breaking down UIs into reusable components that efficiently update and render when data changes. React 19, released in December 2024, is a major version with significant new features and breaking changes. The release includes React Server Components as stable, new hooks like `useActionState`, `useOptimistic`, and `useEffectEvent`, and Actions for handling async operations and form submissions. React 19 removes legacy APIs like `ReactDOM.render()` and `ReactDOM.hydrate()` in favor of `createRoot()` and `hydrateRoot()`, removes support for string refs and legacy context, and eliminates `propTypes` and `defaultProps` (except for classes). The library uses a virtual DOM to optimize rendering performance and supports modern JavaScript patterns including JSX syntax for component templates. React's architecture separates concerns between the core library (react), DOM-specific implementations (react-dom), and various rendering targets, making it adaptable to different platforms while maintaining a consistent API. React 19 includes stable features like Hooks (useState, useEffect, useContext, etc.), Suspense for code splitting and data fetching, server-side rendering with React Server Components, and concurrent features like `useTransition` and `useDeferredValue`. The new JSX Transform from React 17+ means you no longer need to import React when using JSX, and React 19 now uses `createRoot` as the standard rendering method with concurrent features enabled by default. ## Creating and Rendering Components Basic component creation with JSX and rendering to the DOM using the modern createRoot API. ```javascript import { createRoot } from 'react-dom/client'; // Function component (no React import needed for JSX in React 17+) function Welcome({ name, age }) { return (

Hello, {name}!

Age: {age}

); } // Create root and render (React 19 standard) const root = createRoot(document.getElementById('root')); root.render(); // Unmount when done // root.unmount(); ``` ## useState Hook Managing component state with the useState hook for reactive data. ```javascript import { useState } from 'react'; import { createRoot } from 'react-dom/client'; function Counter() { const [count, setCount] = useState(0); const [name, setName] = useState(''); return (

Count: {count}

setName(e.target.value)} placeholder="Enter name" />

Hello, {name}

); } const root = createRoot(document.getElementById('root')); root.render(); ``` ## useEffect Hook Handling side effects like data fetching, subscriptions, and DOM manipulation. ```javascript import { useState, useEffect } from 'react'; import { createRoot } from 'react-dom/client'; function UserProfile({ userId }) { const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { let cancelled = false; async function fetchUser() { try { setLoading(true); const response = await fetch(`https://api.example.com/users/${userId}`); const data = await response.json(); if (!cancelled) { setUser(data); setError(null); } } catch (err) { if (!cancelled) { setError(err.message); } } finally { if (!cancelled) { setLoading(false); } } } fetchUser(); // Cleanup function return () => { cancelled = true; }; }, [userId]); // Re-run when userId changes if (loading) return
Loading...
; if (error) return
Error: {error}
; return
User: {user?.name}
; } const root = createRoot(document.getElementById('root')); root.render(); ``` ## useActionState Hook (React 19) Managing form state and async actions with the new useActionState hook. ```javascript import { useActionState } from 'react'; import { createRoot } from 'react-dom/client'; async function submitForm(previousState, formData) { const name = formData.get('name'); const email = formData.get('email'); // Simulate API call await new Promise(resolve => setTimeout(resolve, 1000)); if (!email.includes('@')) { return { error: 'Invalid email', success: false }; } return { error: null, success: true, message: `Welcome, ${name}!` }; } function ContactForm() { const [state, formAction, isPending] = useActionState(submitForm, { error: null, success: false }); return (
{state.error &&

{state.error}

} {state.success &&

{state.message}

}
); } const root = createRoot(document.getElementById('root')); root.render(); ``` ## useOptimistic Hook (React 19) Displaying optimistic UI updates during async mutations. ```javascript import { useOptimistic, useState } from 'react'; import { createRoot } from 'react-dom/client'; async function sendMessage(message) { // Simulate API call await new Promise(resolve => setTimeout(resolve, 1000)); return { id: Date.now(), text: message, status: 'sent' }; } function MessageList() { const [messages, setMessages] = useState([]); const [optimisticMessages, addOptimisticMessage] = useOptimistic( messages, (state, newMessage) => [...state, { ...newMessage, status: 'sending' }] ); async function handleSend(formData) { const message = formData.get('message'); addOptimisticMessage({ id: 'temp-' + Date.now(), text: message }); const savedMessage = await sendMessage(message); setMessages(msgs => [...msgs, savedMessage]); } return (
    {optimisticMessages.map(msg => (
  • {msg.text} {msg.status === 'sending' ? ' (sending...)' : ' ✓'}
  • ))}
); } const root = createRoot(document.getElementById('root')); root.render(); ``` ## useEffectEvent Hook (React 19.2) Extracting non-reactive logic from effects with the new useEffectEvent hook. ```javascript import { useState, useEffect, useEffectEvent } from 'react'; import { createRoot } from 'react-dom/client'; function ChatRoom({ roomId, theme }) { const [messages, setMessages] = useState([]); // useEffectEvent creates a stable function that can access latest props // without causing the effect to re-run const onConnected = useEffectEvent(() => { // Can access latest theme without it being a dependency console.log(`Connected to ${roomId} with ${theme} theme`); }); useEffect(() => { const connection = createConnection(roomId); connection.on('connected', onConnected); connection.connect(); return () => connection.disconnect(); }, [roomId]); // Only re-run when roomId changes, not theme return
Chat Room: {roomId}
; } const root = createRoot(document.getElementById('root')); root.render(); ``` ## use Hook (React 19) Reading resources like promises and context during render with the use hook. ```javascript import { use, Suspense } from 'react'; import { createRoot } from 'react-dom/client'; async function fetchUser(userId) { const response = await fetch(`https://api.example.com/users/${userId}`); return response.json(); } function UserProfile({ userPromise }) { // use() unwraps the promise during render const user = use(userPromise); return (

{user.name}

{user.email}

); } function App() { const userPromise = fetchUser(123); return ( Loading user...}> ); } const root = createRoot(document.getElementById('root')); root.render(); ``` ## useRef Hook Creating mutable references that persist across renders without triggering updates. ```javascript import { useRef, useEffect, useState } from 'react'; import { createRoot } from 'react-dom/client'; function VideoPlayer() { const videoRef = useRef(null); const renderCountRef = useRef(0); const [isPlaying, setIsPlaying] = useState(false); useEffect(() => { renderCountRef.current += 1; }); function handlePlay() { videoRef.current?.play(); setIsPlaying(true); } function handlePause() { videoRef.current?.pause(); setIsPlaying(false); } return (
); } const root = createRoot(document.getElementById('root')); root.render(); ``` ## useContext Hook Accessing context values for prop drilling avoidance and global state sharing. ```javascript import { createContext, useContext, useState } from 'react'; import { createRoot } from 'react-dom/client'; // In React 19, you can render directly as a provider const ThemeContext = createContext('light'); function ThemeProvider({ children }) { const [theme, setTheme] = useState('light'); return ( {children} ); } function ThemedButton() { const { theme, setTheme } = useContext(ThemeContext); return ( ); } function App() { return ( ); } const root = createRoot(document.getElementById('root')); root.render(); ``` ## useMemo and useCallback Hooks Optimizing performance by memoizing expensive computations and callback functions. ```javascript import { useState, useMemo, useCallback } from 'react'; import { createRoot } from 'react-dom/client'; function ExpensiveList({ items, onItemClick }) { const sortedItems = useMemo(() => { console.log('Sorting items...'); return [...items].sort((a, b) => a.value - b.value); }, [items]); const total = useMemo(() => { return items.reduce((sum, item) => sum + item.value, 0); }, [items]); return (

Total: {total}

    {sortedItems.map(item => (
  • onItemClick(item.id)}> {item.name}: {item.value}
  • ))}
); } function App() { const [items, setItems] = useState([ { id: 1, name: 'Item 1', value: 50 }, { id: 2, name: 'Item 2', value: 30 } ]); const handleItemClick = useCallback((id) => { console.log('Clicked item:', id); }, []); return ; } const root = createRoot(document.getElementById('root')); root.render(); ``` ## useReducer Hook Managing complex state logic with a reducer pattern similar to Redux. ```javascript import { useReducer } from 'react'; import { createRoot } from 'react-dom/client'; const initialState = { count: 0, step: 1 }; function reducer(state, action) { switch (action.type) { case 'increment': return { ...state, count: state.count + state.step }; case 'decrement': return { ...state, count: state.count - state.step }; case 'setStep': return { ...state, step: action.payload }; case 'reset': return initialState; default: throw new Error('Unknown action type'); } } function Counter() { const [state, dispatch] = useReducer(reducer, initialState); return (

Count: {state.count}

Step: {state.step}

dispatch({ type: 'setStep', payload: parseInt(e.target.value) || 1 })} />
); } const root = createRoot(document.getElementById('root')); root.render(); ``` ## Custom Hooks Creating reusable logic by composing built-in hooks into custom hooks. ```javascript import { useState, useEffect } from 'react'; import { createRoot } from 'react-dom/client'; function useLocalStorage(key, initialValue) { const [value, setValue] = useState(() => { try { const item = window.localStorage.getItem(key); return item ? JSON.parse(item) : initialValue; } catch (error) { console.error(error); return initialValue; } }); useEffect(() => { try { window.localStorage.setItem(key, JSON.stringify(value)); } catch (error) { console.error(error); } }, [key, value]); return [value, setValue]; } function useFetch(url) { const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { let cancelled = false; async function fetchData() { try { const response = await fetch(url); const json = await response.json(); if (!cancelled) { setData(json); setError(null); } } catch (err) { if (!cancelled) { setError(err.message); } } finally { if (!cancelled) { setLoading(false); } } } fetchData(); return () => { cancelled = true; }; }, [url]); return { data, loading, error }; } function App() { const [username, setUsername] = useLocalStorage('username', ''); const { data, loading, error } = useFetch('https://api.example.com/data'); return (
setUsername(e.target.value)} placeholder="Username (saved to localStorage)" /> {loading &&

Loading...

} {error &&

Error: {error}

} {data &&
{JSON.stringify(data, null, 2)}
}
); } const root = createRoot(document.getElementById('root')); root.render(); ``` ## useTransition Hook Managing UI responsiveness during expensive state updates with transitions. ```javascript import { useState, useTransition } from 'react'; import { createRoot } from 'react-dom/client'; function SearchApp() { const [query, setQuery] = useState(''); const [isPending, startTransition] = useTransition(); const items = Array.from({ length: 20000 }, (_, i) => `Item ${i} - ${query}` ).filter(item => item.toLowerCase().includes(query.toLowerCase()) ); const handleChange = (e) => { const value = e.target.value; startTransition(() => { setQuery(value); }); }; return (
{isPending &&

Updating...

}

Showing {items.length} results

    {items.slice(0, 100).map((item, i) => (
  • {item}
  • ))}
); } const root = createRoot(document.getElementById('root')); root.render(); ``` ## useDeferredValue Hook Deferring updates to keep the UI responsive with an optional initial value. ```javascript import { useState, useDeferredValue } from 'react'; import { createRoot } from 'react-dom/client'; function SearchApp() { const [query, setQuery] = useState(''); // React 19 supports an initial value for useDeferredValue const deferredQuery = useDeferredValue(query, ''); const items = Array.from({ length: 20000 }, (_, i) => `Item ${i} - ${deferredQuery}` ).filter(item => item.toLowerCase().includes(deferredQuery.toLowerCase()) ); return (
setQuery(e.target.value)} placeholder="Search..." />

Showing {items.length} results

    {items.slice(0, 100).map((item, i) => (
  • {item}
  • ))}
); } const root = createRoot(document.getElementById('root')); root.render(); ``` ## forwardRef and useImperativeHandle Exposing component instance methods to parent components via refs with cleanup support. ```javascript import { forwardRef, useImperativeHandle, useRef, useState } from 'react'; import { createRoot } from 'react-dom/client'; const CustomInput = forwardRef((props, ref) => { const [value, setValue] = useState(''); const inputRef = useRef(null); useImperativeHandle(ref, () => ({ focus() { inputRef.current?.focus(); }, clear() { setValue(''); }, getValue() { return value; } })); return ( setValue(e.target.value)} {...props} /> ); }); function Form() { const inputRef = useRef(null); const handleSubmit = (e) => { e.preventDefault(); alert('Value: ' + inputRef.current.getValue()); inputRef.current.clear(); }; return (
); } const root = createRoot(document.getElementById('root')); root.render(
); ``` ## memo for Component Optimization Preventing unnecessary re-renders by memoizing components based on prop equality. ```javascript import { memo, useState } from 'react'; import { createRoot } from 'react-dom/client'; const ExpensiveComponent = memo(({ data, onUpdate }) => { console.log('ExpensiveComponent rendered'); return (

{data.title}

{data.description}

); }, (prevProps, nextProps) => { // Custom comparison: only re-render if data.id or data.title changes return prevProps.data.id === nextProps.data.id && prevProps.data.title === nextProps.data.title; }); function App() { const [count, setCount] = useState(0); const [data] = useState({ id: 1, title: 'Title', description: 'Description' }); const handleUpdate = (id) => { console.log('Update item:', id); }; return (

Count: {count}

); } const root = createRoot(document.getElementById('root')); root.render(); ``` ## lazy and Suspense for Code Splitting Dynamic component loading with fallback UI during lazy loading transitions. ```javascript import { lazy, Suspense, useState } from 'react'; import { createRoot } from 'react-dom/client'; // Lazy load components const HeavyChart = lazy(() => import('./HeavyChart')); const UserProfile = lazy(() => import('./UserProfile')); function LoadingSpinner() { return
Loading component...
; } function App() { const [showChart, setShowChart] = useState(false); const [showProfile, setShowProfile] = useState(false); return (
{showChart && ( }> )} {showProfile && ( }> )}
); } const root = createRoot(document.getElementById('root')); root.render(); ``` ## Portal for Rendering Outside Hierarchy Rendering components outside the parent DOM hierarchy for modals and tooltips. ```javascript import { useState } from 'react'; import { createPortal } from 'react-dom'; import { createRoot } from 'react-dom/client'; function Modal({ isOpen, onClose, children }) { if (!isOpen) return null; return createPortal(
e.stopPropagation()} > {children}
, document.body ); } function App() { const [isModalOpen, setIsModalOpen] = useState(false); return (

App Content

setIsModalOpen(false)} >

Modal Content

This is rendered outside the parent component hierarchy.

); } const root = createRoot(document.getElementById('root')); root.render(); ``` ## Error Boundaries Catching and handling errors in component trees with error boundary pattern. ```javascript import { Component, useState } from 'react'; import { createRoot } from 'react-dom/client'; class ErrorBoundary extends Component { constructor(props) { super(props); this.state = { hasError: false, error: null, errorInfo: null }; } static getDerivedStateFromError(error) { return { hasError: true }; } componentDidCatch(error, errorInfo) { console.error('Error caught by boundary:', error); console.error('Component stack:', errorInfo.componentStack); this.setState({ error, errorInfo }); } render() { if (this.state.hasError) { return (

Something went wrong.

{this.state.error && this.state.error.toString()}
{this.state.errorInfo?.componentStack}
); } return this.props.children; } } function BuggyComponent({ shouldThrow }) { if (shouldThrow) { throw new Error('Intentional error for demonstration'); } return
Component working correctly
; } function App() { const [shouldThrow, setShouldThrow] = useState(false); return (

Error Boundary Demo

); } const root = createRoot(document.getElementById('root')); root.render(); ``` ## Server-Side Rendering with renderToString Server-side rendering for improved performance and SEO. ```javascript import { renderToString } from 'react-dom/server'; import http from 'http'; function App({ data }) { return ( SSR Example

Server-Rendered Content

Data: {data}

); } const server = http.createServer((req, res) => { const html = renderToString(); res.statusCode = 200; res.setHeader('Content-Type', 'text/html'); res.end(`${html}`); }); server.listen(3000, () => { console.log('Server running on http://localhost:3000'); }); ``` ## Client-Side Hydration Attaching React to server-rendered HTML for interactive client-side functionality using hydrateRoot. ```javascript import { useState } from 'react'; import { hydrateRoot } from 'react-dom/client'; function App({ initialData }) { const [count, setCount] = useState(0); return (

Hydrated App

Initial Data: {initialData}

Count: {count}

); } // Client-side code const container = document.getElementById('root'); const initialData = window.__INITIAL_DATA__; hydrateRoot(container, ); ``` ## Form Actions (React 19) Handling form submissions with the new Actions feature in React 19. ```javascript import { useActionState } from 'react'; import { createRoot } from 'react-dom/client'; async function createUser(previousState, formData) { const username = formData.get('username'); const email = formData.get('email'); // Simulate API call await new Promise(resolve => setTimeout(resolve, 1000)); if (!email.includes('@')) { return { error: 'Invalid email address' }; } return { success: true, message: `User ${username} created successfully!` }; } function SignupForm() { const [state, formAction, isPending] = useActionState(createUser, null); return (
{state?.error && (

{state.error}

)} {state?.success && (

{state.message}

)} ); } const root = createRoot(document.getElementById('root')); root.render(); ``` ## Activity Component (React 19.2) Managing UI state with the new Activity component for hiding and restoring content. ```javascript import { Activity, useState } from 'react'; import { createRoot } from 'react-dom/client'; function ExpensiveComponent() { console.log('ExpensiveComponent rendered'); return (

Expensive Component

This component's state is preserved when hidden

); } function App() { const [isActive, setIsActive] = useState(true); return (
); } const root = createRoot(document.getElementById('root')); root.render(); ``` ## Class Components React 19 still fully supports class components with lifecycle methods. ```javascript import { Component } from 'react'; import { createRoot } from 'react-dom/client'; class Counter extends Component { constructor(props) { super(props); this.state = { count: 0 }; } componentDidMount() { console.log('Counter mounted'); } componentDidUpdate(prevProps, prevState) { console.log('Counter updated:', prevState.count, '->', this.state.count); } componentWillUnmount() { console.log('Counter will unmount'); } increment = () => { this.setState(prevState => ({ count: prevState.count + 1 })); } render() { return (

Count: {this.state.count}

); } } const root = createRoot(document.getElementById('root')); root.render(); ``` ## Summary React 19 is a major release that removes legacy features and introduces powerful new APIs for building modern web applications. The most significant changes include the removal of `ReactDOM.render()` in favor of `createRoot()` as the standard rendering method, making concurrent features the default. React 19 removes string refs, legacy context, `propTypes`, `defaultProps` (except for classes), and the UMD builds. The new JSX Transform means you no longer need to import React when using JSX. React 19 introduces Actions for handling async operations, with new hooks like `useActionState` for form handling, `useOptimistic` for optimistic UI updates, and the `use()` hook for reading promises and context during render. Context providers can now be used directly as `` instead of ``, and refs now support cleanup functions. React 19 includes stable React Server Components and Server Actions, comprehensive support for document metadata through APIs like `preload`, `preinit`, `preconnect`, and improvements to hydration error messages with diffs for easier debugging. The release adds support for Custom Elements, Popover API, and new events like `onScrollEnd`. React 19.2 introduces additional features like the `` component for managing UI visibility state, `useEffectEvent` for extracting non-reactive logic from effects, and `cacheSignal` for RSC cache lifetime management. TypeScript support has been significantly improved with better type inference for `useReducer`, refs now mutable by default, and stricter `ReactElement` typing. Combined with enhanced server-side rendering capabilities, improved error handling, and concurrent features like `useTransition` and `useDeferredValue` as stable APIs, React 19 provides a solid foundation for building performant, scalable applications with modern patterns while maintaining backward compatibility for essential features like class components and error boundaries.