react 19

React 19 introduces powerful new features for building modern web applications with enhanced server capabilities, improved form handling, and better performance.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "react 19" with this command: npx skills add slanycukr/riot-api-project/slanycukr-riot-api-project-react-19

React 19 Development

React 19 introduces powerful new features for building modern web applications with enhanced server capabilities, improved form handling, and better performance.

Quick Start

Basic Component with Hooks

import { useState, useEffect } from "react";

function Counter() { const [count, setCount] = useState(0);

useEffect(() => { console.log("Count changed:", count); }, [count]);

return ( <div> <p>Count: {count}</p> <button onClick={() => setCount(count + 1)}>Increment</button> </div> ); }

Custom Hook for API Data

import { useState, useEffect } from "react";

function useApiData(url) { const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null);

useEffect(() => { const fetchData = async () => { try { const response = await fetch(url); const result = await response.json(); setData(result); } catch (err) { setError(err); } finally { setLoading(false); } };

fetchData();

}, [url]);

return { data, loading, error }; }

// Usage function UserProfile({ userId }) { const { data: user, loading, error } = useApiData(/api/users/${userId});

if (loading) return <div>Loading...</div>; if (error) return <div>Error: {error.message}</div>; if (!user) return <div>No user found</div>;

return <div>{user.name}</div>; }

React 19 New Features

Server Actions and Forms

// Server action "use server"; async function updateUser(formData) { const name = formData.get("name"); const email = formData.get("email");

// Database update logic here await db.users.update({ name, email });

return { success: true, message: "User updated successfully" }; }

// Client component with form function UserForm({ user }) { const [state, formAction, isPending] = useActionState(updateUser, null);

return ( <form action={formAction}> <input name="name" defaultValue={user.name} /> <input name="email" defaultValue={user.email} /> <button type="submit" disabled={isPending}> {isPending ? "Updating..." : "Update"} </button> {state?.message && <p>{state.message}</p>} </form> ); }

Form Status Hook

import { useFormStatus } from "react-dom";

function SubmitButton() { const { pending } = useFormStatus();

return ( <button type="submit" disabled={pending}> {pending ? "Submitting..." : "Submit"} </button> ); }

function ContactForm() { return ( <form action={submitContact}> <input name="name" placeholder="Your name" /> <input name="email" placeholder="Your email" /> <SubmitButton /> </form> ); }

Server Components

// Server Component (runs on server) async function BlogPost({ id }) { const post = await db.posts.find(id);

return ( <article> <h1>{post.title}</h1> <p>{post.content}</p> <CommentSection postId={post.id} /> </article> ); }

// Client Component for interactivity ("use client"); function CommentSection({ postId }) { const [comments, setComments] = useState([]); const [newComment, setNewComment] = useState("");

const addComment = async () => { // Client-side logic for adding comments };

return ( <div> <h3>Comments</h3> {/* Comment rendering and form */} </div> ); }

Common Patterns

State Management with Context

import { createContext, useContext, useState, useReducer } from "react";

// Create context const AuthContext = createContext();

// Auth provider component function AuthProvider({ children }) { const [user, setUser] = useState(null);

const login = async (credentials) => { // Login logic setUser(userData); };

const logout = () => { setUser(null); };

return ( <AuthContext.Provider value={{ user, login, logout }}> {children} </AuthContext.Provider> ); }

// Custom hook for consuming context function useAuth() { const context = useContext(AuthContext); if (!context) { throw new Error("useAuth must be used within AuthProvider"); } return context; }

// Usage in components function Header() { const { user, logout } = useAuth();

return ( <header> {user ? ( <div> <span>Welcome, {user.name}</span> <button onClick={logout}>Logout</button> </div> ) : ( <div>Please log in</div> )} </header> ); }

Data Fetching with Suspense

import { Suspense } from "react";

// Async component async function UserList() { const users = await fetchUsers(); // async function

return ( <ul> {users.map((user) => ( <li key={user.id}>{user.name}</li> ))} </ul> ); }

// Using Suspense boundary function App() { return ( <div> <h1>Users</h1> <Suspense fallback={<div>Loading users...</div>}> <UserList /> </Suspense> </div> ); }

Optimistic Updates

import { useState, useTransition } from "react";

function TodoList() { const [todos, setTodos] = useState(initialTodos); const [isPending, startTransition] = useTransition();

const addTodo = async (newTodo) => { // Optimistic update const optimisticId = Date.now(); startTransition(() => { setTodos((prev) => [ ...prev, { id: optimisticId, text: newTodo, status: "optimistic", }, ]); });

try {
  const savedTodo = await saveTodo(newTodo);
  // Replace optimistic todo with saved one
  setTodos((prev) =>
    prev.map((todo) => (todo.id === optimisticId ? savedTodo : todo)),
  );
} catch (error) {
  // Revert optimistic update on error
  setTodos((prev) => prev.filter((todo) => todo.id !== optimisticId));
}

};

return ( <div> <ul> {todos.map((todo) => ( <li key={todo.id} style={{ opacity: todo.status === "optimistic" ? 0.5 : 1 }} > {todo.text} </li> ))} </ul> <button onClick={() => addTodo("New task")} disabled={isPending}> Add Todo </button> </div> ); }

Error Boundaries

import { Component } from "react";

class ErrorBoundary extends Component { constructor(props) { super(props); this.state = { hasError: false, error: null }; }

static getDerivedStateFromError(error) { return { hasError: true, error }; }

componentDidCatch(error, errorInfo) { console.error("Error caught by boundary:", error, errorInfo); }

render() { if (this.state.hasError) { return ( <div> <h2>Something went wrong</h2> <details>{this.state.error?.message}</details> </div> ); }

return this.props.children;

} }

// Usage function App() { return ( <ErrorBoundary> <MyComponent /> </ErrorBoundary> ); }

Performance Patterns

Memoization with useMemo and useCallback

import { useState, useMemo, useCallback } from "react";

function ExpensiveComponent({ data, onItemClick }) { const [filter, setFilter] = useState("");

// Memoize expensive computation const filteredData = useMemo(() => { console.log("Filtering data..."); return data.filter((item) => item.name.toLowerCase().includes(filter.toLowerCase()), ); }, [data, filter]);

// Memoize event handler const handleItemClick = useCallback( (item) => { onItemClick(item); }, [onItemClick], );

return ( <div> <input value={filter} onChange={(e) => setFilter(e.target.value)} placeholder="Filter items..." /> <ul> {filteredData.map((item) => ( <li key={item.id} onClick={() => handleItemClick(item)}> {item.name} </li> ))} </ul> </div> ); }

Code Splitting with lazy loading

import { lazy, Suspense } from "react";

// Lazy load component const AdminDashboard = lazy(() => import("./AdminDashboard"));

function App() { const [isAdmin, setIsAdmin] = useState(false);

return ( <div> <h1>My App</h1> <button onClick={() => setIsAdmin(true)}>Admin View</button>

  {isAdmin &#x26;&#x26; (
    &#x3C;Suspense fallback={&#x3C;div>Loading admin dashboard...&#x3C;/div>}>
      &#x3C;AdminDashboard />
    &#x3C;/Suspense>
  )}
&#x3C;/div>

); }

Best Practices

Component Structure

// Good: Single responsibility components function UserAvatar({ user, size = "medium" }) { return ( <img src={user.avatar} alt={user.name} className={avatar avatar-${size}} /> ); }

function UserCard({ user }) { return ( <div className="user-card"> <UserAvatar user={user} size="large" /> <h3>{user.name}</h3> <p>{user.email}</p> </div> ); }

Prop Types and Default Values

import PropTypes from "prop-types";

function Button({ children, variant = "primary", size = "medium", onClick, disabled = false, }) { const className = btn btn-${variant} btn-${size};

return ( <button className={className} onClick={onClick} disabled={disabled}> {children} </button> ); }

Button.propTypes = { children: PropTypes.node.isRequired, variant: PropTypes.oneOf(["primary", "secondary", "danger"]), size: PropTypes.oneOf(["small", "medium", "large"]), onClick: PropTypes.func, disabled: PropTypes.bool, };

Requirements

  • React 19.0 or higher

  • Node.js 18+ (for development)

  • Modern browser with ES6+ support

Dependencies for Full React 19 Experience

npm install react@19 react-dom@19

Recommended Development Tools

npm install --save-dev @types/react @types/react-dom

Common Additional Libraries

  • State Management: zustand , jotai , or Context API

  • Routing: react-router-dom

  • Data Fetching: @tanstack/react-query

  • Form Handling: Built-in React 19 forms or react-hook-form

  • Styling: tailwindcss , styled-components , or CSS modules

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

axios

No summary provided by upstream source.

Repository SourceNeeds Review
General

radix-ui

No summary provided by upstream source.

Repository SourceNeeds Review
General

httpx

No summary provided by upstream source.

Repository SourceNeeds Review