Files
bodyshop/_reference/REACT_19_FEATURES_GUIDE.md

11 KiB

React 19 Features Guide

Overview

This guide covers the new React 19 features available in our codebase and provides practical examples for implementing them.


1. New Hooks for Forms

useFormStatus - Track Form Submission State

What it does: Provides access to the current form's submission status without manual state management.

Use Case: Show loading states on submit buttons, disable inputs during submission.

Example:

import { useFormStatus } from 'react';

function SubmitButton() {
  const { pending } = useFormStatus();
  
  return (
    <button type="submit" disabled={pending}>
      {pending ? 'Saving...' : 'Save'}
    </button>
  );
}

function JobForm({ onSave }) {
  return (
    <form action={onSave}>
      <input name="jobNumber" />
      <SubmitButton />
    </form>
  );
}

Benefits:

  • No manual useState for loading states
  • Automatic re-renders when form status changes
  • Better separation of concerns (button doesn't need form state)

useOptimistic - Instant UI Updates

What it does: Updates UI immediately while async operations complete in the background.

Use Case: Comments, notes, status updates - anything where you want instant feedback.

Example:

import { useState, useOptimistic } from 'react';

function JobNotes({ jobId, initialNotes }) {
  const [notes, setNotes] = useState(initialNotes);
  const [optimisticNotes, addOptimisticNote] = useOptimistic(
    notes,
    (current, newNote) => [...current, newNote]
  );

  async function handleAddNote(formData) {
    const text = formData.get('note');
    const tempNote = { id: Date.now(), text, pending: true };
    
    // Show immediately
    addOptimisticNote(tempNote);
    
    // Save to server
    const saved = await saveNote(jobId, text);
    setNotes([...notes, saved]);
  }

  return (
    <form action={handleAddNote}>
      <textarea name="note" />
      <button type="submit">Add Note</button>
      <ul>
        {optimisticNotes.map(note => (
          <li key={note.id} style={{ opacity: note.pending ? 0.5 : 1 }}>
            {note.text}
          </li>
        ))}
      </ul>
    </form>
  );
}

Benefits:

  • Perceived performance improvement
  • Better UX - users see changes instantly
  • Automatic rollback on error (if implemented)

useActionState - Complete Form State Management

What it does: Manages async form submissions with built-in loading, error, and success states.

Use Case: Form validation, API submissions, complex form workflows.

Example:

import { useActionState } from 'react';

async function createContract(prevState, formData) {
  const data = {
    customerId: formData.get('customerId'),
    vehicleId: formData.get('vehicleId'),
  };
  
  try {
    const result = await fetch('/api/contracts', {
      method: 'POST',
      body: JSON.stringify(data),
    });
    
    if (!result.ok) {
      return { error: 'Failed to create contract', data: null };
    }
    
    return { error: null, data: await result.json() };
  } catch (err) {
    return { error: err.message, data: null };
  }
}

function ContractForm() {
  const [state, submitAction, isPending] = useActionState(
    createContract,
    { error: null, data: null }
  );

  return (
    <form action={submitAction}>
      <input name="customerId" required />
      <input name="vehicleId" required />
      
      <button type="submit" disabled={isPending}>
        {isPending ? 'Creating...' : 'Create Contract'}
      </button>
      
      {state.error && <div className="error">{state.error}</div>}
      {state.data && <div className="success">Contract #{state.data.id} created!</div>}
    </form>
  );
}

Benefits:

  • Replaces multiple useState calls
  • Built-in pending state
  • Cleaner error handling
  • Type-safe with TypeScript

2. Actions API

The Actions API simplifies form submissions and async operations by using the native action prop on forms.

Traditional Approach (React 18):

function OldForm() {
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);
  
  async function handleSubmit(e) {
    e.preventDefault();
    setLoading(true);
    setError(null);
    
    try {
      const formData = new FormData(e.target);
      await saveData(formData);
    } catch (err) {
      setError(err.message);
    } finally {
      setLoading(false);
    }
  }
  
  return (
    <form onSubmit={handleSubmit}>
      {/* form fields */}
    </form>
  );
}

Modern Approach (React 19):

import { useActionState } from 'react';

function NewForm() {
  const [state, formAction, isPending] = useActionState(async (_, formData) => {
    return await saveData(formData);
  }, null);
  
  return (
    <form action={formAction}>
      {/* form fields */}
    </form>
  );
}

3. Practical Implementation Examples

Example 1: Owner/Customer Form with Optimistic UI

import { useOptimistic, useActionState } from 'react';
import { Form, Input, Button } from 'antd';

function OwnerFormModern({ owner, onSave }) {
  const [optimisticOwner, setOptimisticOwner] = useOptimistic(
    owner,
    (current, updates) => ({ ...current, ...updates })
  );
  
  const [state, submitAction, isPending] = useActionState(
    async (_, formData) => {
      const updates = {
        name: formData.get('name'),
        phone: formData.get('phone'),
        email: formData.get('email'),
      };
      
      // Show changes immediately
      setOptimisticOwner(updates);
      
      // Save to server
      try {
        await onSave(updates);
        return { success: true };
      } catch (error) {
        return { success: false, error: error.message };
      }
    },
    { success: null }
  );

  return (
    <form action={submitAction}>
      <Form.Item label="Name">
        <Input name="name" defaultValue={optimisticOwner.name} />
      </Form.Item>
      
      <Form.Item label="Phone">
        <Input name="phone" defaultValue={optimisticOwner.phone} />
      </Form.Item>
      
      <Form.Item label="Email">
        <Input name="email" defaultValue={optimisticOwner.email} />
      </Form.Item>
      
      <Button type="primary" htmlType="submit" loading={isPending}>
        {isPending ? 'Saving...' : 'Save Owner'}
      </Button>
      
      {state.error && <div className="error">{state.error}</div>}
    </form>
  );
}

Example 2: Job Status Update with useFormStatus

import { useFormStatus } from 'react';

function JobStatusButton({ status }) {
  const { pending } = useFormStatus();
  
  return (
    <button disabled={pending}>
      {pending ? 'Updating...' : `Mark as ${status}`}
    </button>
  );
}

function JobStatusForm({ jobId, currentStatus }) {
  async function updateStatus(formData) {
    const newStatus = formData.get('status');
    await fetch(`/api/jobs/${jobId}/status`, {
      method: 'PATCH',
      body: JSON.stringify({ status: newStatus }),
    });
  }

  return (
    <form action={updateStatus}>
      <input type="hidden" name="status" value="IN_PROGRESS" />
      <JobStatusButton status="In Progress" />
    </form>
  );
}

4. Third-Party Library Compatibility

Fully Compatible (Already in use)

  1. Ant Design 6.2.0

    • Full React 19 support out of the box
    • No patches or workarounds needed
    • 📝 Note: Ant Design 6 was built with React 19 in mind
  2. React-Redux 9.2.0

    • Full React 19 support
    • All hooks (useSelector, useDispatch) work correctly
    • 📝 Tip: Continue using hooks over connect() HOC
  3. Apollo Client 4.0.13

    • Compatible with React 19
    • useQuery, useMutation work correctly
    • 📝 Note: Supports React 19's concurrent features
  4. React Router 7.12.0

    • Full React 19 support
    • All navigation hooks compatible
    • Future flags enabled for optimal performance

Integration Notes

All our major dependencies are already compatible with React 19:

  • No additional patches needed
  • No breaking changes in current code
  • All hooks and patterns continue to work

5. Migration Strategy

Gradual Adoption Approach

Phase 1: Learn (Current)

  • Review this guide
  • Understand new hooks and patterns
  • Identify good candidates for migration

Phase 2: Pilot (Recommended)

  • Start with new features/forms
  • Try useActionState in one new form
  • Measure developer experience improvement

Phase 3: Refactor (Optional)

  • Gradually update high-traffic forms
  • Add optimistic UI to user-facing features
  • Simplify complex form state management

Good Candidates for React 19 Features

  1. Forms with Complex Loading States

    • Contract creation
    • Job creation/editing
    • Owner/Vehicle forms
    • → Use useActionState
  2. Instant Feedback Features

    • Adding job notes
    • Status updates
    • Comments/messages
    • → Use useOptimistic
  3. Submit Buttons

    • Any form button that needs loading state
    • → Use useFormStatus

Don't Rush to Refactor

Keep using current patterns for:

  • Ant Design Form components (already excellent)
  • Redux for global state
  • Apollo Client for GraphQL
  • Existing working code

Only refactor when:

  • Building new features
  • Fixing bugs in forms
  • Simplifying overly complex state management

6. Performance Improvements in React 19

Automatic Optimizations

React 19 includes built-in compiler optimizations that automatically improve performance:

  1. Automatic Memoization

    • Less need for useMemo and useCallback
    • Components automatically optimize re-renders
  2. Improved Concurrent Rendering

    • Better handling of heavy operations
    • Smoother UI during data loading
  3. Enhanced Suspense

    • Better loading states
    • Improved streaming SSR

What this means for us:

  • Existing code may run faster without changes
  • Future code will be easier to write
  • Less manual optimization needed

7. Resources

Official Documentation

Migration Guides

Community Resources


8. Summary

Current Status

All dependencies compatible with React 19

  • Ant Design 6.2.0 ✓
  • React-Redux 9.2.0 ✓
  • Apollo Client 4.0.13 ✓
  • React Router 7.12.0 ✓

New Features Available

🎯 Ready to use in new code:

  • useFormStatus - Track form submission state
  • useOptimistic - Instant UI updates
  • useActionState - Complete form state management
  • Actions API - Cleaner form handling

Recommendations

  1. No immediate action required - Everything works
  2. 🎯 Start using new features in new code - Especially forms
  3. 📚 Learn gradually - No need to refactor everything
  4. 🚀 Enjoy performance improvements - Automatic optimizations active

Questions or Need Help?

Feel free to:

  • Try examples in a branch first
  • Ask the team for code reviews
  • Share patterns that work well
  • Document new patterns you discover

Happy coding with React 19! 🎉