Back to Blog
    Web Development

    React 19: New Features, Server Components & What Changed — Complete Guide with Examples

    Mortex Solutions TeamFebruary 15, 202615 min read
    React 19: New Features, Server Components & What Changed — Complete Guide with Examples

    React 19 is the most significant React release in years, bringing server-first architecture, a new compilation model, and simplified APIs that fundamentally change how we build React applications. Whether you're starting fresh or migrating, this guide covers everything.

    React development code on screen

    🚀 The Big Changes at a Glance

    • React Compiler — Automatic memoisation, no more manual useMemo/useCallback
    • Actions — First-class support for form submissions and mutations
    • use() hook — Read promises and context anywhere, including conditionally
    • Server Components (stable) — Components that run on the server by default
    • Document Metadata — Native <title>, <meta>, <link> support in components

    1. React Compiler — Automatic Memoisation

    The React Compiler (formerly React Forget) analyses your code at build time and automatically inserts memoisation. This eliminates the need for useMemo, useCallback, and React.memo in most cases.

    Before (React 18)

    import { useMemo, useCallback } from 'react';
    
    function ProductList({ products, onSelect }) {
      const sorted = useMemo(
        () => products.sort((a, b) => a.price - b.price),
        [products]
      );
    
      const handleClick = useCallback(
        (id) => onSelect(id),
        [onSelect]
      );
    
      return sorted.map(p => (
        <ProductCard key={p.id} product={p} onClick={handleClick} />
      ));
    }

    After (React 19)

    // No manual memoisation needed — the compiler handles it!
    function ProductList({ products, onSelect }) {
      const sorted = products.sort((a, b) => a.price - b.price);
    
      return sorted.map(p => (
        <ProductCard key={p.id} product={p} onClick={() => onSelect(p.id)} />
      ));
    }

    2. Actions — Simplified Form Handling

    Actions replace the old pattern of onSubmit + useState + try/catch for mutations. They work with both client and server functions.

    function ContactForm() {
      async function submitForm(formData) {
        'use server';
        const name = formData.get('name');
        const email = formData.get('email');
        await db.contacts.create({ name, email });
      }
    
      return (
        <form action={submitForm}>
          <input name="name" placeholder="Name" />
          <input name="email" type="email" placeholder="Email" />
          <button type="submit">Send</button>
        </form>
      );
    }

    3. The use() Hook

    The use() hook reads async resources like promises and context — and unlike other hooks, it can be called inside conditionals and loops.

    import { use, Suspense } from 'react';
    
    function UserProfile({ userPromise }) {
      const user = use(userPromise); // Suspends until resolved
    
      return (
        <div>
          <h2>{user.name}</h2>
          <p>{user.email}</p>
        </div>
      );
    }
    
    // Usage
    <Suspense fallback={<Skeleton />}>
      <UserProfile userPromise={fetchUser(id)} />
    </Suspense>

    4. Document Metadata in Components

    You can now render <title>, <meta>, and <link> directly in your components — React hoists them to <head> automatically.

    function BlogPost({ post }) {
      return (
        <article>
          <title>{post.title} | My Blog</title>
          <meta name="description" content={post.excerpt} />
          <h1>{post.title}</h1>
          <p>{post.content}</p>
        </article>
      );
    }

    Migration Tips

    1. Remove unnecessary useMemo and useCallback calls
    2. Replace forwardRef — refs are now passed as regular props
    3. Update form handling to use Actions where possible
    4. Adopt use() for data fetching with Suspense
    5. Run the React 19 codemod: npx @react-codemod/react-19
    💡 Key Takeaway: React 19 makes React simpler, faster, and more server-friendly. The compiler alone can boost performance 2-3x in large apps without changing a single line of code.