- Add React Router with theme browser, theme detail, and layout detail pages - Implement manifest-based theme discovery for better performance - Add Welcome component as home page with feature overview - Fix layout and styling issues with proper CSS centering - Implement introspective theme browsing (dynamically discover colors/variables) - Add layout preview system with iframe scaling - Create comprehensive theme detail page with color palette display - Fix TypeScript errors and build issues - Remove hardcoded theme assumptions in favor of dynamic discovery 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
7.0 KiB
7.0 KiB
React 19 Guidelines & Best Practices
Based on React 19 Release Blog
Core Philosophy
"React 19 provides powerful tools to create more responsive, efficient web applications with simplified state management and rendering strategies."
Key New Features
1. Actions
Actions simplify data mutations and state updates by automatically managing:
- Pending states - know when operations are in progress
- Optimistic updates - update UI before server confirms
- Error handling - graceful error recovery
- Form submissions - streamlined form processing
// Example: Using Actions for form submission
function UpdateName({ name, updateName }) {
const [isPending, startTransition] = useTransition();
return (
<form action={updateName}>
<input name="name" defaultValue={name} />
<button type="submit" disabled={isPending}>
{isPending ? 'Updating...' : 'Update'}
</button>
</form>
);
}
2. New Hooks
useActionState
Simplifies action handling with built-in state management:
function MyComponent() {
const [state, formAction] = useActionState(actionFunction, initialState);
return (
<form action={formAction}>
{/* Form elements */}
</form>
);
}
useOptimistic
Enables optimistic UI updates for responsive user experience:
function TodoList({ todos, addTodo }) {
const [optimisticTodos, addOptimisticTodo] = useOptimistic(
todos,
(state, newTodo) => [...state, { ...newTodo, sending: true }]
);
async function formAction(formData) {
addOptimisticTodo({ name: formData.get("name") });
await addTodo(formData);
}
return (
<form action={formAction}>
{optimisticTodos.map(todo => (
<div key={todo.id} className={todo.sending ? "sending" : ""}>
{todo.name}
</div>
))}
</form>
);
}
useFormStatus
Provides form submission status:
function SubmitButton() {
const { pending, data, method, action } = useFormStatus();
return (
<button type="submit" disabled={pending}>
{pending ? 'Submitting...' : 'Submit'}
</button>
);
}
use
Reads resources during rendering:
function Profile({ userPromise }) {
const user = use(userPromise);
return <h1>{user.name}</h1>;
}
3. Improved Component Rendering
ref
as a Prop
Function components can now receive ref
as a regular prop:
function MyInput({ placeholder, ref }) {
return <input placeholder={placeholder} ref={ref} />;
}
// Usage
<MyInput ref={inputRef} placeholder="Enter text" />
Direct Context Rendering
Context can be rendered directly without .Provider
:
// Before React 19
<ThemeContext.Provider value={theme}>
<App />
</ThemeContext.Provider>
// React 19
<ThemeContext value={theme}>
<App />
</ThemeContext>
Cleanup Functions for Refs
function MyComponent() {
const ref = useCallback((node) => {
if (node) {
// Setup
node.focus();
// Cleanup function
return () => {
node.blur();
};
}
}, []);
return <input ref={ref} />;
}
Metadata Support
Components can render metadata tags directly:
function BlogPost({ post }) {
return (
<article>
<title>{post.title}</title>
<meta name="description" content={post.excerpt} />
<h1>{post.title}</h1>
<p>{post.content}</p>
</article>
);
}
4. Performance Enhancements
Resource Preloading
import { preload, preinit } from 'react-dom';
// Preload resources
preload('/api/user', { as: 'fetch' });
preinit('/styles.css', { as: 'style' });
Better Hydration Error Reporting
- More detailed error messages
- Better debugging information
- Improved compatibility with third-party scripts
5. Server Components
Server-Side Rendering
// Server Component
async function BlogPost({ slug }) {
const post = await fetchPost(slug);
return (
<article>
<h1>{post.title}</h1>
<p>{post.content}</p>
</article>
);
}
Server Actions
// actions.js
'use server'
export async function updateUser(formData) {
const name = formData.get('name');
// Update user on server
await database.updateUser({ name });
}
// Component
import { updateUser } from './actions.js';
function UserForm() {
return (
<form action={updateUser}>
<input name="name" />
<button type="submit">Update</button>
</form>
);
}
Best Practices for Our Project
1. Forms and Data Management
- Use Actions for theme selection and configuration
- Implement useOptimistic for responsive theme preview
- Leverage useFormStatus for loading states
2. Component Design
- Use ref as prop for theme slot components
- Implement cleanup functions for theme CSS loading
- Render metadata for theme preview information
3. Performance
- Preload theme assets using new preloading APIs
- Use Server Components for theme discovery if server-side rendering is added
- Implement error boundaries with improved error handling
4. State Management
- Use useActionState for complex theme operations
- Implement optimistic updates for theme switching
- Leverage new Context syntax for theme providers
Implementation Guidelines
Theme Selection with Actions
function ThemeBrowser({ themes }) {
const [selectedTheme, selectTheme] = useActionState(
async (currentState, formData) => {
const themeId = formData.get('themeId');
const theme = await loadTheme(themeId);
return theme;
},
null
);
return (
<form>
{themes.map(theme => (
<button
key={theme.id}
formAction={() => selectTheme(new FormData([['themeId', theme.id]]))}
>
{theme.name}
</button>
))}
</form>
);
}
Optimistic Theme Switching
function ThemePreview({ currentTheme, onThemeChange }) {
const [optimisticTheme, setOptimisticTheme] = useOptimistic(
currentTheme,
(state, newTheme) => newTheme
);
async function switchTheme(newTheme) {
setOptimisticTheme(newTheme);
await onThemeChange(newTheme);
}
return (
<div className={`theme-preview theme-${optimisticTheme.id}`}>
<h3>{optimisticTheme.name}</h3>
{/* Theme preview content */}
</div>
);
}
Theme Context (New Syntax)
function App() {
const [theme, setTheme] = useState(defaultTheme);
return (
<ThemeContext value={{ theme, setTheme }}>
<ThemeBrowser />
<SlideEditor />
</ThemeContext>
);
}
Key Takeaways
- Embrace Actions - Simplify form handling and state management
- Use Optimistic Updates - Create responsive user interfaces
- Leverage New Hooks - Reduce boilerplate code
- Improve Performance - Utilize preloading and better error handling
- Simplify Context - Use direct rendering without
.Provider
- Handle Refs Better - Pass refs as regular props to function components