react-development

安装量: 53
排名: #13915

安装

npx skills add https://github.com/manutej/luxor-claude-marketplace --skill react-development

React Development Skill

This skill provides comprehensive guidance for building modern React applications using hooks, components, state management, context, effects, and performance optimization techniques based on official React documentation from react.dev.

When to Use This Skill

Use this skill when:

Building single-page applications (SPAs) with React Creating reusable UI components and component libraries Managing complex application state with hooks and context Implementing forms, data fetching, and side effects Optimizing React application performance Building interactive user interfaces with dynamic data Migrating class components to functional components with hooks Implementing global state management without external libraries Creating custom hooks for reusable logic Building accessible and performant web applications Core Concepts Components

Components are the building blocks of React applications. They let you split the UI into independent, reusable pieces.

Functional Components (Modern Approach):

function Welcome(props) { return

Hello, {props.name}

; }

// Arrow function syntax const Greeting = ({ name, age }) => { return (

{name}

Age: {age}

); };

Component Composition:

function App() { return (

); }

JSX

JSX is a syntax extension for JavaScript that looks similar to HTML. It produces React elements.

JSX Fundamentals:

// Embedding expressions const name = 'Josh Perez'; const element =

Hello, {name}

;

// JSX attributes const image = {user.name};

// JSX children const container = (

Welcome

Get started with React

);

// Conditional rendering const greeting = (

{isLoggedIn ? : }

);

// Lists and keys const numbers = [1, 2, 3, 4, 5]; const listItems = numbers.map((number) =>

  • {number}
  • );

    Props

    Props are arguments passed into React components. They are passed to components via HTML attributes.

    Passing and Using Props:

    function Product({ name, price, inStock }) { return (

    {name}

    ${price}

    {inStock ? In Stock : Out of Stock}
    ); }

    // Usage

    Props with Children:

    function Card({ title, children }) { return (

    {title}

    {children}
    ); }

    // Usage

    This is the card content

    Default Props:

    function Button({ text = 'Click me', variant = 'primary' }) { return ; }

    State

    State is a component's memory. It lets components remember information and respond to user interactions.

    Local Component State:

    import { useState } from 'react';

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

    return (

    Count: {count}

    ); }

    React Hooks

    Hooks let you use state and other React features in functional components.

    useState

    The useState hook lets you add state to functional components.

    Basic Usage:

    import { useState } from 'react';

    function Form() { const [name, setName] = useState(''); const [email, setEmail] = useState('');

    const handleSubmit = (e) => { e.preventDefault(); console.log({ name, email }); };

    return (

    setName(e.target.value)} placeholder="Name" /> setEmail(e.target.value)} placeholder="Email" type="email" />
    ); }

    State with Objects:

    function UserProfile() { const [user, setUser] = useState({ name: '', age: 0, email: '' });

    const updateField = (field, value) => { setUser(prev => ({ ...prev, [field]: value })); };

    return (

    updateField('name', e.target.value)} /> updateField('age', parseInt(e.target.value))} /> updateField('email', e.target.value)} />
    ); }

    State with Arrays:

    function TodoList() { const [todos, setTodos] = useState([]); const [input, setInput] = useState('');

    const addTodo = () => { setTodos(prev => [...prev, { id: Date.now(), text: input }]); setInput(''); };

    const removeTodo = (id) => { setTodos(prev => prev.filter(todo => todo.id !== id)); };

    return (

    setInput(e.target.value)} />
      {todos.map(todo => (
    • {todo.text}
    • ))}
    ); }

    useEffect

    The useEffect hook lets you perform side effects in functional components.

    Basic Side Effects:

    import { useState, useEffect } from 'react';

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

    useEffect(() => { document.title = Count: ${count}; }, [count]);

    return ( ); }

    Data Fetching:

    function UserData({ 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(`/api/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();
    
    return () => {
      cancelled = true;
    };
    

    }, [userId]);

    if (loading) return

    Loading...
    ; if (error) return
    Error: {error}
    ;

    return

    {user?.name}
    ; }

    Event Listeners and Cleanup:

    function WindowSize() { const [size, setSize] = useState({ width: window.innerWidth, height: window.innerHeight });

    useEffect(() => { function handleResize() { setSize({ width: window.innerWidth, height: window.innerHeight }); }

    window.addEventListener('resize', handleResize);
    
    // Cleanup function
    return () => {
      window.removeEventListener('resize', handleResize);
    };
    

    }, []); // Empty dependency array = run once on mount

    return

    {size.width} x {size.height}
    ; }

    Timers and Intervals:

    function Timer() { const [seconds, setSeconds] = useState(0); const [isRunning, setIsRunning] = useState(false);

    useEffect(() => { if (!isRunning) return;

    const interval = setInterval(() => {
      setSeconds(s => s + 1);
    }, 1000);
    
    return () => clearInterval(interval);
    

    }, [isRunning]);

    return (

    Seconds: {seconds}

    ); }

    useContext

    The useContext hook lets you read and subscribe to context from your component.

    Creating and Using Context:

    import { createContext, useContext, useState } from 'react';

    const ThemeContext = createContext('light');

    function App() { const [theme, setTheme] = useState('light');

    return ( ); }

    function Toolbar() { return (

    ); }

    function ThemedButton() { const theme = useContext(ThemeContext);

    return ( ); }

    Multiple Contexts:

    const ThemeContext = createContext('light'); const UserContext = createContext(null);

    function App() { const [theme, setTheme] = useState('light'); const [currentUser, setCurrentUser] = useState({ name: 'John', role: 'admin' });

    return ( ); }

    function Dashboard() { const theme = useContext(ThemeContext); const user = useContext(UserContext);

    return (

    Welcome, {user.name}

    Role: {user.role}

    ); }

    useReducer

    The useReducer hook is an alternative to useState for managing complex state logic.

    Basic Reducer Pattern:

    import { useReducer } from 'react';

    function counterReducer(state, action) { switch (action.type) { case 'increment': return { count: state.count + 1 }; case 'decrement': return { count: state.count - 1 }; case 'reset': return { count: 0 }; default: throw new Error(Unknown action: ${action.type}); } }

    function Counter() { const [state, dispatch] = useReducer(counterReducer, { count: 0 });

    return (

    Count: {state.count}

    ); }

    Complex State Management (Task List Pattern from Context7):

    function tasksReducer(tasks, action) { switch (action.type) { case 'added': { return [...tasks, { id: action.id, text: action.text, done: false }]; } case 'changed': { return tasks.map(t => { if (t.id === action.task.id) { return action.task; } else { return t; } }); } case 'deleted': { return tasks.filter(t => t.id !== action.id); } default: { throw Error('Unknown action: ' + action.type); } } }

    function TaskApp() { const [tasks, dispatch] = useReducer(tasksReducer, initialTasks);

    function handleAddTask(text) { dispatch({ type: 'added', id: nextId++, text: text, }); }

    function handleChangeTask(task) { dispatch({ type: 'changed', task: task }); }

    function handleDeleteTask(taskId) { dispatch({ type: 'deleted', id: taskId }); }

    return ( <>

    Prague itinerary

    </> ); }

    let nextId = 3; const initialTasks = [ { id: 0, text: 'Visit Kafka Museum', done: true }, { id: 1, text: 'Watch a puppet show', done: false }, { id: 2, text: 'Lennon Wall pic', done: false } ];

    useMemo

    The useMemo hook lets you cache the result of expensive calculations.

    Memoizing Expensive Calculations:

    import { useMemo, useState } from 'react';

    function ProductList({ products, category }) { const [sortOrder, setSortOrder] = useState('asc');

    const filteredAndSortedProducts = useMemo(() => { console.log('Filtering and sorting products...');

    const filtered = products.filter(p => p.category === category);
    
    return filtered.sort((a, b) => {
      if (sortOrder === 'asc') {
        return a.price - b.price;
      }
      return b.price - a.price;
    });
    

    }, [products, category, sortOrder]);

    return (

      {filteredAndSortedProducts.map(product => (
    • {product.name} - ${product.price}
    • ))}
    ); }

    Preventing Object Recreation:

    function SearchResults({ query }) { const searchOptions = useMemo(() => ({ query, limit: 10, caseSensitive: false }), [query]);

    // searchOptions object only recreated when query changes const results = useSearch(searchOptions);

    return ; }

    useCallback

    The useCallback hook lets you cache a function definition between re-renders.

    Memoizing Event Handlers:

    import { useCallback, useState } from 'react';

    function ProductPage({ productId }) { const [items, setItems] = useState([]);

    const handleAddToCart = useCallback(() => { setItems(prevItems => [...prevItems, productId]); }, [productId]);

    return ; }

    // Memoized child component const AddToCartButton = memo(({ onAdd }) => { console.log('Button rendered'); return ; });

    Optimizing Child Components:

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

    const handleToggle = useCallback((id) => { setTodos(prevTodos => prevTodos.map(todo => todo.id === id ? { ...todo, done: !todo.done } : todo ) ); }, []);

    const handleDelete = useCallback((id) => { setTodos(prevTodos => prevTodos.filter(todo => todo.id !== id)); }, []);

    return (

      {todos.map(todo => ( ))}
    ); }

    useRef

    The useRef hook lets you reference a value that's not needed for rendering.

    Accessing DOM Elements:

    import { useRef } from 'react';

    function TextInput() { const inputRef = useRef(null);

    function handleClick() { inputRef.current.focus(); }

    return ( <> </> ); }

    Storing Mutable Values:

    function Stopwatch() { const [time, setTime] = useState(0); const intervalRef = useRef(null);

    function handleStart() { intervalRef.current = setInterval(() => { setTime(t => t + 1); }, 10); }

    function handleStop() { clearInterval(intervalRef.current); }

    return (

    Time: {(time / 100).toFixed(2)}s

    ); }

    Video Player Control (Context7 Pattern):

    import { useRef, useState } from 'react';

    function VideoPlayer({ src, isPlaying }) { const ref = useRef(null);

    useEffect(() => { if (isPlaying) { ref.current.play(); } else { ref.current.pause(); } }, [isPlaying]);

    return

    function App() { const [isPlaying, setIsPlaying] = useState(false);

    return ( <> </> ); }

    State Management Patterns Local State Pattern

    Use local state for component-specific data that doesn't need to be shared.

    function LoginForm() { const [formData, setFormData] = useState({ username: '', password: '', rememberMe: false }); const [errors, setErrors] = useState({}); const [isSubmitting, setIsSubmitting] = useState(false);

    const handleChange = (field) => (e) => { const value = e.target.type === 'checkbox' ? e.target.checked : e.target.value; setFormData(prev => ({ ...prev, [field]: value })); };

    const validate = () => { const newErrors = {}; if (!formData.username) newErrors.username = 'Required'; if (!formData.password) newErrors.password = 'Required'; return newErrors; };

    const handleSubmit = async (e) => { e.preventDefault(); const newErrors = validate();

    if (Object.keys(newErrors).length > 0) {
      setErrors(newErrors);
      return;
    }
    
    setIsSubmitting(true);
    try {
      await login(formData);
    } catch (error) {
      setErrors({ submit: error.message });
    } finally {
      setIsSubmitting(false);
    }
    

    };

    return (

    {errors.username && {errors.username}}

      <input
        type="password"
        value={formData.password}
        onChange={handleChange('password')}
        placeholder="Password"
      />
      {errors.password && <span>{errors.password}</span>}
    
      <label>
        <input
          type="checkbox"
          checked={formData.rememberMe}
          onChange={handleChange('rememberMe')}
        />
        Remember me
      </label>
    
      <button type="submit" disabled={isSubmitting}>
        {isSubmitting ? 'Logging in...' : 'Log in'}
      </button>
    
      {errors.submit && <div>{errors.submit}</div>}
    </form>
    

    ); }

    Context API Pattern

    Use Context for global or widely-shared state like themes, user authentication, or preferences.

    Theme Context with Provider:

    import { createContext, useContext, useState } from 'react';

    const ThemeContext = createContext(null);

    export function ThemeProvider({ children }) { const [theme, setTheme] = useState('light');

    const toggleTheme = () => { setTheme(prevTheme => prevTheme === 'light' ? 'dark' : 'light'); };

    return ( {children} ); }

    export function useTheme() { const context = useContext(ThemeContext); if (!context) { throw new Error('useTheme must be used within ThemeProvider'); } return context; }

    // Usage function App() { return ( ); }

    function Page() { const { theme, toggleTheme } = useTheme();

    return (

    page-${theme}}>
    ); }

    Reducer + Context Pattern (Context7 Best Practice)

    Combine useReducer with Context for scalable state management.

    Task Management with Reducer + Context:

    import { createContext, useContext, useReducer } from 'react';

    // Context for tasks data const TasksContext = createContext(null);

    // Context for dispatch function const TasksDispatchContext = createContext(null);

    export function TasksProvider({ children }) { const [tasks, dispatch] = useReducer(tasksReducer, initialTasks);

    return ( {children} ); }

    export function useTasks() { return useContext(TasksContext); }

    export function useTasksDispatch() { return useContext(TasksDispatchContext); }

    function tasksReducer(tasks, action) { switch (action.type) { case 'added': { return [...tasks, { id: action.id, text: action.text, done: false }]; } case 'changed': { return tasks.map(t => { if (t.id === action.task.id) { return action.task; } return t; }); } case 'deleted': { return tasks.filter(t => t.id !== action.id); } default: { throw Error('Unknown action: ' + action.type); } } }

    const initialTasks = [ { id: 0, text: 'Philosopher's Path', done: true }, { id: 1, text: 'Visit the temple', done: false }, { id: 2, text: 'Drink matcha', done: false } ];

    // Component using the pattern function AddTask() { const [text, setText] = useState(''); const dispatch = useTasksDispatch();

    return ( <> setText(e.target.value)} /> </> ); }

    function TaskList() { const tasks = useTasks(); return (

      {tasks.map(task => ( ))}
    ); }

    function Task({ task }) { const [isEditing, setIsEditing] = useState(false); const dispatch = useTasksDispatch();

    let taskContent; if (isEditing) { taskContent = ( <> { dispatch({ type: 'changed', task: { ...task, text: e.target.value } }); }} /> </> ); } else { taskContent = ( <> {task.text} </> ); }

    return ( ); }

    let nextId = 3;

    Custom Hooks

    Custom hooks let you extract component logic into reusable functions.

    Basic Custom Hook import { useState, useEffect } from 'react';

    function useWindowSize() { const [size, setSize] = useState({ width: window.innerWidth, height: window.innerHeight });

    useEffect(() => { function handleResize() { setSize({ width: window.innerWidth, height: window.innerHeight }); }

    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
    

    }, []);

    return size; }

    // Usage function Component() { const { width, height } = useWindowSize(); return

    {width} x {height}
    ; }

    Online Status Hook (Context7 Pattern) import { useState, useEffect } from 'react';

    function useOnlineStatus() { const [isOnline, setIsOnline] = useState(true);

    useEffect(() => { function handleOnline() { setIsOnline(true); }

    function handleOffline() {
      setIsOnline(false);
    }
    
    window.addEventListener('online', handleOnline);
    window.addEventListener('offline', handleOffline);
    
    return () => {
      window.removeEventListener('online', handleOnline);
      window.removeEventListener('offline', handleOffline);
    };
    

    }, []);

    return isOnline; }

    // Usage function StatusBar() { const isOnline = useOnlineStatus(); return

    {isOnline ? '✅ Online' : '❌ Disconnected'}

    ; }

    Form Hook function useForm(initialValues, onSubmit) { const [values, setValues] = useState(initialValues); const [errors, setErrors] = useState({}); const [isSubmitting, setIsSubmitting] = useState(false);

    const handleChange = (name, value) => { setValues(prev => ({ ...prev, [name]: value })); // Clear error when user starts typing if (errors[name]) { setErrors(prev => ({ ...prev, [name]: null })); } };

    const handleSubmit = async (e) => { e.preventDefault(); setIsSubmitting(true);

    try {
      await onSubmit(values);
    } catch (error) {
      setErrors({ submit: error.message });
    } finally {
      setIsSubmitting(false);
    }
    

    };

    const reset = () => { setValues(initialValues); setErrors({}); };

    return { values, errors, isSubmitting, handleChange, handleSubmit, setErrors, reset }; }

    // Usage function ContactForm() { const { values, errors, isSubmitting, handleChange, handleSubmit } = useForm( { name: '', email: '', message: '' }, async (data) => { await fetch('/api/contact', { method: 'POST', body: JSON.stringify(data) }); } );

    return ( handleChange('name', e.target.value)} /> {errors.name && {errors.name}}

      <input
        value={values.email}
        onChange={(e) => handleChange('email', e.target.value)}
      />
      {errors.email && <span>{errors.email}</span>}
    
      <textarea
        value={values.message}
        onChange={(e) => handleChange('message', e.target.value)}
      />
      {errors.message && <span>{errors.message}</span>}
    
      <button type="submit" disabled={isSubmitting}>
        {isSubmitting ? 'Sending...' : 'Send'}
      </button>
    </form>
    

    ); }

    Fetch Hook function useFetch(url, options = {}) { const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null);

    useEffect(() => { let cancelled = false;

    async function fetchData() {
      try {
        setLoading(true);
        const response = await fetch(url, options);
    
        if (!response.ok) {
          throw new Error(`HTTP error! status: ${response.status}`);
        }
    
        const result = await response.json();
    
        if (!cancelled) {
          setData(result);
          setError(null);
        }
      } catch (err) {
        if (!cancelled) {
          setError(err.message);
          setData(null);
        }
      } finally {
        if (!cancelled) {
          setLoading(false);
        }
      }
    }
    
    fetchData();
    
    return () => {
      cancelled = true;
    };
    

    }, [url, JSON.stringify(options)]);

    return { data, loading, error }; }

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

    if (loading) return

    Loading...
    ; if (error) return
    Error: {error}
    ;

    return

    {data.name}
    ; }

    Local Storage Hook function useLocalStorage(key, initialValue) { const [storedValue, setStoredValue] = useState(() => { try { const item = window.localStorage.getItem(key); return item ? JSON.parse(item) : initialValue; } catch (error) { console.error(error); return initialValue; } });

    const setValue = (value) => { try { const valueToStore = value instanceof Function ? value(storedValue) : value; setStoredValue(valueToStore); window.localStorage.setItem(key, JSON.stringify(valueToStore)); } catch (error) { console.error(error); } };

    return [storedValue, setValue]; }

    // Usage function Settings() { const [theme, setTheme] = useLocalStorage('theme', 'light'); const [fontSize, setFontSize] = useLocalStorage('fontSize', 16);

    return (

      <input
        type="number"
        value={fontSize}
        onChange={(e) => setFontSize(parseInt(e.target.value))}
      />
    </div>
    

    ); }

    Performance Optimization React.memo

    Memoize components to prevent unnecessary re-renders.

    import { memo } from 'react';

    const ExpensiveComponent = memo(function ExpensiveComponent({ data, onAction }) { console.log('Rendering expensive component');

    return (

    {data.map(item => (
    {item.name}
    ))}
    ); });

    // With custom comparison const CustomMemoComponent = memo( function Component({ user }) { return

    {user.name}
    ; }, (prevProps, nextProps) => { // Return true if props are equal (skip re-render) return prevProps.user.id === nextProps.user.id; } );

    Lazy Loading

    Load components on demand to reduce initial bundle size.

    import { lazy, Suspense } from 'react';

    const HeavyComponent = lazy(() => import('./HeavyComponent')); const AdminPanel = lazy(() => import('./AdminPanel'));

    function App() { return (

    Loading...\
    }>
    ); }

    // Lazy loading with routes function Dashboard() { const [showAdmin, setShowAdmin] = useState(false);

    return (

      {showAdmin && (
        <Suspense fallback={<Spinner />}>
          <AdminPanel />
        </Suspense>
      )}
    </div>
    

    ); }

    Code Splitting

    Split your code into smaller chunks for better performance.

    import { lazy, Suspense } from 'react'; import { BrowserRouter, Routes, Route } from 'react-router-dom';

    const Home = lazy(() => import('./pages/Home')); const About = lazy(() => import('./pages/About')); const Dashboard = lazy(() => import('./pages/Dashboard'));

    function App() { return ( Loading page...\

    }> } /> } /> } /> ); }

    Virtual Scrolling

    Render only visible items in large lists.

    function VirtualList({ items, height, itemHeight }) { const [scrollTop, setScrollTop] = useState(0);

    const startIndex = Math.floor(scrollTop / itemHeight); const endIndex = Math.min( startIndex + Math.ceil(height / itemHeight), items.length );

    const visibleItems = items.slice(startIndex, endIndex);

    const offsetY = startIndex * itemHeight; const totalHeight = items.length * itemHeight;

    return (

    setScrollTop(e.target.scrollTop)} >
    translateY(${offsetY}px) }}> {visibleItems.map((item, index) => (
    {item}
    ))}
    ); }

    Best Practices from Context7 Research 1. Proper Dependency Arrays

    Always include all dependencies in useEffect, useMemo, and useCallback.

    // ❌ Bad - missing dependencies useEffect(() => { fetchData(userId); }, []);

    // ✅ Good - all dependencies included useEffect(() => { fetchData(userId); }, [userId]);

    1. Cleanup Functions

    Always cleanup side effects to prevent memory leaks.

    useEffect(() => { const subscription = api.subscribe(id);

    return () => { subscription.unsubscribe(); }; }, [id]);

    1. Separate Concerns

    Split context for data and dispatch to optimize re-renders.

    // ✅ Good - separate contexts const TasksContext = createContext(null); const TasksDispatchContext = createContext(null);

    // Components that only dispatch won't re-render when tasks change function AddTask() { const dispatch = useTasksDispatch(); // No re-render when tasks change // ... }

    1. Avoid Inline Object Creation

    Use useMemo or useCallback to prevent unnecessary re-renders.

    // ❌ Bad - new object on every render

    // ✅ Good - memoized object const style = useMemo(() => ({ margin: 10 }), []);

    1. State Updater Functions

    Use updater functions when new state depends on previous state.

    // ❌ Bad - may use stale state setCount(count + 1);

    // ✅ Good - uses current state setCount(prevCount => prevCount + 1);

    1. Extract Complex Logic

    Move complex state logic to reducers or custom hooks.

    // ✅ Good - complex logic in reducer function cartReducer(state, action) { switch (action.type) { case 'add_item': // Complex logic here return newState; case 'remove_item': // Complex logic here return newState; default: return state; } }

    1. Key Props for Lists

    Always provide unique keys for list items.

    // ❌ Bad - using index as key {items.map((item, index) =>

    {item}
    )}

    // ✅ Good - using unique ID {items.map(item =>

    {item.text}
    )}

    1. Controlled Components

    Prefer controlled components for form inputs.

    function Form() { const [value, setValue] = useState('');

    return ( setValue(e.target.value)} /> ); }

    1. Error Boundaries

    Implement error boundaries to catch and handle errors gracefully.

    class ErrorBoundary extends React.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:', error, errorInfo); }

    render() { if (this.state.hasError) { return

    Something went wrong.

    ; }

    return this.props.children;
    

    } }

    // Usage

    1. Prop Types or TypeScript

    Use PropTypes or TypeScript for type checking.

    import PropTypes from 'prop-types';

    function User({ name, age, email }) { return

    {name} ({age})
    ; }

    User.propTypes = { name: PropTypes.string.isRequired, age: PropTypes.number.isRequired, email: PropTypes.string };

    User.defaultProps = { email: 'no-email@example.com' };

    Additional Examples Example 1: Multi-Step Form function MultiStepForm() { const [step, setStep] = useState(1); const [formData, setFormData] = useState({ personalInfo: {}, address: {}, preferences: {} });

    const updateFormData = (section, data) => { setFormData(prev => ({ ...prev, [section]: { ...prev[section], ...data } })); };

    const nextStep = () => setStep(s => s + 1); const prevStep = () => setStep(s => s - 1);

    return (

    {step === 1 && ( { updateFormData('personalInfo', data); nextStep(); }} /> )} {step === 2 && ( { updateFormData('address', data); nextStep(); }} onPrev={prevStep} /> )} {step === 3 && ( { updateFormData('preferences', data); submitForm({ ...formData, preferences: data }); }} onPrev={prevStep} /> )}
    ); }

    Example 2: Infinite Scroll function InfiniteScroll() { const [items, setItems] = useState([]); const [page, setPage] = useState(1); const [loading, setLoading] = useState(false); const [hasMore, setHasMore] = useState(true);

    const loadMore = useCallback(async () => { if (loading || !hasMore) return;

    setLoading(true);
    try {
      const newItems = await fetchItems(page);
      setItems(prev => [...prev, ...newItems]);
      setHasMore(newItems.length > 0);
      setPage(p => p + 1);
    } finally {
      setLoading(false);
    }
    

    }, [page, loading, hasMore]);

    useEffect(() => { const handleScroll = () => { if ( window.innerHeight + window.scrollY >= document.documentElement.scrollHeight - 500 ) { loadMore(); } };

    window.addEventListener('scroll', handleScroll);
    return () => window.removeEventListener('scroll', handleScroll);
    

    }, [loadMore]);

    return (

    {items.map(item => )} {loading &&
    Loading...
    } {!hasMore &&
    No more items
    }
    ); }

    Example 3: Debounced Search function useDebounce(value, delay) { const [debouncedValue, setDebouncedValue] = useState(value);

    useEffect(() => { const handler = setTimeout(() => { setDebouncedValue(value); }, delay);

    return () => {
      clearTimeout(handler);
    };
    

    }, [value, delay]);

    return debouncedValue; }

    function SearchComponent() { const [searchTerm, setSearchTerm] = useState(''); const debouncedSearchTerm = useDebounce(searchTerm, 500); const [results, setResults] = useState([]);

    useEffect(() => { if (debouncedSearchTerm) { searchAPI(debouncedSearchTerm).then(setResults); } else { setResults([]); } }, [debouncedSearchTerm]);

    return (

    setSearchTerm(e.target.value)} placeholder="Search..." />
      {results.map(result => (
    • {result.title}
    • ))}
    ); }

    Example 4: Modal with Portal import { createPortal } from 'react-dom';

    function Modal({ isOpen, onClose, children }) { if (!isOpen) return null;

    return createPortal(

    e.stopPropagation()}> {children}
    , document.body ); }

    // Usage function App() { const [isModalOpen, setIsModalOpen] = useState(false);

    return (

    setIsModalOpen(false)}>

    Modal Content

    This is a modal dialog

    ); }

    Example 5: Drag and Drop function DragDropList() { const [items, setItems] = useState([ { id: 1, text: 'Item 1' }, { id: 2, text: 'Item 2' }, { id: 3, text: 'Item 3' } ]);

    const [draggedItem, setDraggedItem] = useState(null);

    const handleDragStart = (item) => { setDraggedItem(item); };

    const handleDragOver = (e) => { e.preventDefault(); };

    const handleDrop = (targetItem) => { if (!draggedItem || draggedItem.id === targetItem.id) return;

    const draggedIndex = items.findIndex(i => i.id === draggedItem.id);
    const targetIndex = items.findIndex(i => i.id === targetItem.id);
    
    const newItems = [...items];
    newItems.splice(draggedIndex, 1);
    newItems.splice(targetIndex, 0, draggedItem);
    
    setItems(newItems);
    setDraggedItem(null);
    

    };

    return (

      {items.map(item => (
    • handleDragStart(item)} onDragOver={handleDragOver} onDrop={() => handleDrop(item)} > {item.text}
    • ))}
    ); }

    Summary

    This React development skill covers:

    Core Concepts: Components, JSX, Props, State Essential Hooks: useState, useEffect, useContext, useReducer, useMemo, useCallback, useRef State Management: Local state, Context API, Reducer + Context pattern Custom Hooks: Reusable logic extraction patterns Performance: Memoization, lazy loading, code splitting, virtual scrolling Best Practices: From Context7 research including proper dependencies, cleanup, separation of concerns Real-world Examples: Forms, infinite scroll, search, modals, drag-and-drop

    The patterns and examples are based on official React documentation (Trust Score: 10) and represent modern React development practices focusing on functional components and hooks.

    返回排行榜