# React中的性能优化

# 性能优化概述

React应用在规模增长后可能面临性能挑战,尤其是在处理大量数据和复杂UI时。性能优化的目标是提供流畅的用户体验,减少加载时间和交互延迟。本章将介绍多种React性能优化技术,从渲染优化到代码分割,从状态管理到网络请求。

# 为什么需要性能优化

  1. 提升用户体验:减少卡顿和延迟
  2. 降低资源消耗:减少内存使用和CPU负载
  3. 提高可扩展性:支持更多数据和更复杂的交互
  4. 改善移动体验:在性能受限的设备上提供更好的体验
  5. 降低运营成本:减少服务器负载和带宽消耗

# 性能问题的常见表现

  • 页面加载缓慢
  • 交互响应延迟
  • 滚动卡顿
  • 动画不流畅
  • 内存泄漏
  • 网络请求过多或过慢

# 性能优化的思路

优化React应用性能通常围绕以下几个方向:

  1. 减少不必要的渲染
  2. 减小打包体积
  3. 优化加载策略
  4. 提高渲染效率
  5. 优化状态管理
  6. 减少网络请求

# 渲染优化

# 使用React.memo避免不必要的重渲染

当父组件重新渲染时,即使props未发生变化,子组件也会重新渲染。使用React.memo可以避免这种情况:

// 未优化的组件
function Button({ text, onClick }) {
  console.log('Button rendered');
  return <button onClick={onClick}>{text}</button>;
}

// 使用React.memo优化
const MemoizedButton = React.memo(function Button({ text, onClick }) {
  console.log('Button rendered');
  return <button onClick={onClick}>{text}</button>;
});

React.memo接受第二个参数,允许自定义比较逻辑:

const MemoizedComponent = React.memo(
  Component,
  (prevProps, nextProps) => {
    // 返回true表示不重新渲染
    return prevProps.complexProp.id === nextProps.complexProp.id;
  }
);

# 使用useMemo缓存计算结果

对于复杂计算,使用useMemo可以避免在每次渲染时重新计算:

function ProductList({ products, filter }) {
  // 未优化:每次渲染都会过滤
  // const filteredProducts = products.filter(product => 
  //   product.name.includes(filter)
  // );
  
  // 优化:仅在products或filter变化时重新计算
  const filteredProducts = useMemo(() => {
    console.log('Filtering products');
    return products.filter(product => 
      product.name.includes(filter)
    );
  }, [products, filter]);
  
  return (
    <ul>
      {filteredProducts.map(product => (
        <li key={product.id}>{product.name}</li>
      ))}
    </ul>
  );
}

# 使用useCallback缓存函数

对于传递给子组件的函数,使用useCallback可以避免不必要的重新渲染:

function Parent() {
  const [count, setCount] = useState(0);
  const [text, setText] = useState('');
  
  // 不优化:每次Parent渲染都会创建新函数
  // const handleClick = () => {
  //   console.log('Button clicked');
  // };
  
  // 优化:只在特定依赖变化时创建新函数
  const handleClick = useCallback(() => {
    console.log('Button clicked', count);
  }, [count]); // 只有count变化时才创建新函数
  
  return (
    <div>
      <input value={text} onChange={e => setText(e.target.value)} />
      <MemoizedButton text="Click me" onClick={handleClick} />
    </div>
  );
}

# 避免内联对象和函数

每次渲染时,内联对象和函数都会创建新实例,可能导致不必要的重新渲染:

// 不优化:每次渲染都创建新的样式对象和处理函数
function Component() {
  return (
    <Button 
      style={{ color: 'red' }}
      onClick={() => console.log('Clicked')}
    />
  );
}

// 优化:使用常量样式和useCallback
function OptimizedComponent() {
  const buttonStyle = { color: 'red' };
  const handleClick = useCallback(() => console.log('Clicked'), []);
  
  return (
    <Button 
      style={buttonStyle}
      onClick={handleClick}
    />
  );
}

# 延迟加载非关键组件

使用React的lazySuspense延迟加载非关键组件:

import React, { lazy, Suspense } from 'react';

// 延迟加载重量级组件
const HeavyComponent = lazy(() => import('./HeavyComponent'));

function App() {
  return (
    <div>
      <Header />
      <MainContent />
      <Suspense fallback={<div>Loading...</div>}>
        <HeavyComponent />
      </Suspense>
      <Footer />
    </div>
  );
}

# 数据结构和算法优化

# 使用不可变数据结构

使用不可变数据结构可以简化状态管理和提高比较性能:

// 不优化:直接修改对象
function updateUser(user, newName) {
  user.name = newName; // 直接修改对象
  return user;
}

// 优化:创建新对象
function updateUserImmutably(user, newName) {
  return { ...user, name: newName }; // 创建新对象
}

// 使用immer简化不可变更新
import produce from 'immer';

function updateUserWithImmer(user, newName) {
  return produce(user, draft => {
    draft.name = newName;
  });
}

# 优化大型列表

处理大型列表时,可以使用虚拟化技术,只渲染可见项:

import { FixedSizeList } from 'react-window';

function VirtualizedList({ items }) {
  const Row = ({ index, style }) => (
    <div style={style}>
      {items[index].name}
    </div>
  );
  
  return (
    <FixedSizeList
      height={500}
      width={300}
      itemCount={items.length}
      itemSize={35} // 每项高度
    >
      {Row}
    </FixedSizeList>
  );
}

对于更复杂的场景,可以使用react-virtualizedreact-virtual库。

# 优化复杂表单

对于复杂表单,可以考虑只更新变化的字段,而不是整个表单状态:

import { useState } from 'react';

// 不优化:整体状态更新
function SimpleForm() {
  const [formState, setFormState] = useState({
    name: '',
    email: '',
    phone: '',
    address: '',
    // ...更多字段
  });
  
  const handleChange = (e) => {
    setFormState({
      ...formState,
      [e.target.name]: e.target.value
    });
  };
  
  return (
    <form>
      <input
        name="name"
        value={formState.name}
        onChange={handleChange}
      />
      {/* 更多输入字段 */}
    </form>
  );
}

// 优化:拆分状态
function OptimizedForm() {
  const [name, setName] = useState('');
  const [email, setEmail] = useState('');
  const [phone, setPhone] = useState('');
  // ...更多状态
  
  return (
    <form>
      <input
        name="name"
        value={name}
        onChange={(e) => setName(e.target.value)}
      />
      {/* 更多输入字段 */}
    </form>
  );
}

# 状态管理优化

# 状态设计原则

  • 最小化状态:只存储必要的数据
  • 规范化状态:避免嵌套和重复数据
  • 本地化状态:状态尽可能接近使用它的组件
  • 派生状态:从已有状态计算派生值,而不是存储重复状态

# 使用Context API时的性能考虑

Context API在状态变化时会触发所有消费组件重新渲染。可以通过拆分Context来减少不必要的渲染:

// 不优化:单一大Context
const AppContext = createContext();

function AppProvider({ children }) {
  const [user, setUser] = useState(null);
  const [theme, setTheme] = useState('light');
  const [notifications, setNotifications] = useState([]);
  
  const value = {
    user, setUser,
    theme, setTheme,
    notifications, setNotifications
  };
  
  return (
    <AppContext.Provider value={value}>
      {children}
    </AppContext.Provider>
  );
}

// 优化:拆分Context
const UserContext = createContext();
const ThemeContext = createContext();
const NotificationContext = createContext();

function AppProvider({ children }) {
  const [user, setUser] = useState(null);
  const [theme, setTheme] = useState('light');
  const [notifications, setNotifications] = useState([]);
  
  return (
    <UserContext.Provider value={{ user, setUser }}>
      <ThemeContext.Provider value={{ theme, setTheme }}>
        <NotificationContext.Provider value={{ notifications, setNotifications }}>
          {children}
        </NotificationContext.Provider>
      </ThemeContext.Provider>
    </UserContext.Provider>
  );
}

# 优化Redux使用

Redux中的性能优化关键点:

  1. 正确使用选择器
// 不优化:每次获取整个状态
const mapStateToProps = (state) => ({
  user: state.user,
  posts: state.posts,
});

// 优化:只获取需要的属性
const mapStateToProps = (state) => ({
  userName: state.user.name,
  postCount: state.posts.length,
});

// 使用reselect缓存派生数据
import { createSelector } from 'reselect';

const selectPosts = state => state.posts;
const selectSearchTerm = state => state.searchTerm;

const selectFilteredPosts = createSelector(
  [selectPosts, selectSearchTerm],
  (posts, searchTerm) => posts.filter(post => 
    post.title.includes(searchTerm)
  )
);
  1. 避免不必要的对象创建
// 不优化:mapDispatchToProps 对象形式会在每次渲染时创建新对象
const mapDispatchToProps = {
  increment: () => ({ type: 'INCREMENT' }),
  decrement: () => ({ type: 'DECREMENT' }),
};

// 优化:使用函数形式
const mapDispatchToProps = (dispatch) => ({
  increment: () => dispatch({ type: 'INCREMENT' }),
  decrement: () => dispatch({ type: 'DECREMENT' }),
});

// 或使用bindActionCreators
import { bindActionCreators } from 'redux';
import * as actions from './actions';

const mapDispatchToProps = (dispatch) => 
  bindActionCreators(actions, dispatch);
  1. 使用Redux Toolkit

Redux Toolkit内置了许多性能优化,包括不可变更新、Action创建和Thunk:

import { createSlice } from '@reduxjs/toolkit';

const counterSlice = createSlice({
  name: 'counter',
  initialState: { value: 0 },
  reducers: {
    increment: state => {
      // 内部使用Immer,可以直接"修改"状态
      state.value += 1;
    },
    decrement: state => {
      state.value -= 1;
    },
  }
});

export const { increment, decrement } = counterSlice.actions;
export default counterSlice.reducer;

# 优化构建和部署

# 代码分割

使用动态导入实现代码分割:

// 路由级代码分割
import { lazy, Suspense } from 'react';
import { Route, Routes } 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 (
    <Suspense fallback={<div>Loading...</div>}>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
        <Route path="/dashboard/*" element={<Dashboard />} />
      </Routes>
    </Suspense>
  );
}

# 减小包体积

  1. Tree Shaking:确保只导入需要的模块:
// 不优化:导入整个库
import * as lodash from 'lodash';

// 优化:只导入需要的函数
import debounce from 'lodash/debounce';
  1. 使用生产构建
# 使用Create React App时
npm run build

# 手动webpack配置
webpack --mode production
  1. 分析和优化包大小
# 安装包分析工具
npm install --save-dev source-map-explorer

# 在package.json中添加命令
"scripts": {
  "analyze": "source-map-explorer 'build/static/js/*.js'"
}

# 运行分析
npm run build
npm run analyze
  1. 优化图片和媒体资源
// 使用适当的图片格式和大小
import smallImage from './images/small.webp';

// 使用懒加载图片
import { LazyLoadImage } from 'react-lazy-load-image-component';

function ProductItem({ product }) {
  return (
    <div>
      <LazyLoadImage
        src={product.imageUrl}
        alt={product.name}
        effect="blur"
        threshold={300}
      />
      <h3>{product.name}</h3>
    </div>
  );
}

# 利用CDN提升加载速度

将静态资源部署到CDN可以显著提升加载速度:

<!-- 使用CDN加载React -->
<script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>

<!-- 使用CDN加载其他库 -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" />

# React 18特有的性能优化

# 自动批处理(Automatic Batching)

React 18默认启用了自动批处理,将多个状态更新合并为一次渲染:

// React 17中:这会导致两次渲染
function handleClick() {
  setCount(c => c + 1); // 触发渲染
  setFlag(f => !f); // 触发渲染
}

// React 18中:这只会触发一次渲染
function handleClick() {
  setCount(c => c + 1); // 不会立即渲染
  setFlag(f => !f); // 不会立即渲染
  // React会在事件处理结束后批量更新
}

# 使用useTransition处理大型更新

useTransition可以将状态更新标记为非紧急,提高应用响应性:

import { useState, useTransition } from 'react';

function SearchResults() {
  const [query, setQuery] = useState('');
  const [results, setResults] = useState([]);
  const [isPending, startTransition] = useTransition();
  
  function handleChange(e) {
    // 立即更新输入值(高优先级)
    setQuery(e.target.value);
    
    // 标记为过渡更新(低优先级)
    startTransition(() => {
      // 耗时的过滤操作
      const filtered = filterItems(e.target.value);
      setResults(filtered);
    });
  }
  
  return (
    <>
      <input value={query} onChange={handleChange} />
      {isPending ? <div>Loading...</div> : (
        <ul>
          {results.map(item => (
            <li key={item.id}>{item.name}</li>
          ))}
        </ul>
      )}
    </>
  );
}

# 使用useDeferredValue处理延迟值

useDeferredValue可以为频繁更新的值创建延迟版本:

import { useState, useDeferredValue, useMemo } from 'react';

function SearchPage() {
  const [query, setQuery] = useState('');
  // 创建一个延迟版本的query
  const deferredQuery = useDeferredValue(query);
  
  // 耗时的列表计算,使用延迟值
  const items = useMemo(() => {
    return searchItems(deferredQuery);
  }, [deferredQuery]);
  
  return (
    <>
      <input value={query} onChange={e => setQuery(e.target.value)} />
      <ItemList items={items} />
    </>
  );
}

# 使用startTransition实现并发渲染

使用startTransition标记较低优先级的更新:

import { startTransition } from 'react';

function TabContainer() {
  const [tab, setTab] = useState('home');
  
  function selectTab(nextTab) {
    // 将标签切换标记为非紧急
    startTransition(() => {
      setTab(nextTab);
    });
  }
  
  return (
    <>
      <TabButton 
        isActive={tab === 'home'}
        onClick={() => selectTab('home')}
      >
        Home
      </TabButton>
      <TabButton 
        isActive={tab === 'about'}
        onClick={() => selectTab('about')}
      >
        About
      </TabButton>
      <TabContent tab={tab} />
    </>
  );
}

# 网络请求优化

# 使用React Query优化数据获取

React Query提供了自动缓存、重试、预取和失效处理:

import { useQuery, useMutation, useQueryClient } from 'react-query';

// 获取数据
function TodoList() {
  const { data, isLoading, error } = useQuery(
    'todos', 
    fetchTodos,
    {
      staleTime: 5 * 60 * 1000, // 5分钟内不重新获取
      cacheTime: 30 * 60 * 1000, // 缓存30分钟
    }
  );
  
  if (isLoading) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;
  
  return (
    <ul>
      {data.map(todo => (
        <li key={todo.id}>{todo.title}</li>
      ))}
    </ul>
  );
}

// 修改数据
function AddTodo() {
  const queryClient = useQueryClient();
  
  const mutation = useMutation(addTodo, {
    // 乐观更新
    onMutate: async (newTodo) => {
      // 取消相关查询
      await queryClient.cancelQueries('todos');
      
      // 保存旧数据
      const previousTodos = queryClient.getQueryData('todos');
      
      // 乐观更新缓存
      queryClient.setQueryData('todos', old => [
        ...old, 
        { id: Date.now(), ...newTodo }
      ]);
      
      return { previousTodos };
    },
    // 出错时回滚
    onError: (err, newTodo, context) => {
      queryClient.setQueryData('todos', context.previousTodos);
    },
    // 成功时使查询无效
    onSettled: () => {
      queryClient.invalidateQueries('todos');
    },
  });
  
  return (
    <form onSubmit={(e) => {
      e.preventDefault();
      mutation.mutate({ title: e.target.todo.value });
      e.target.reset();
    }}>
      <input name="todo" />
      <button type="submit">Add</button>
    </form>
  );
}

# 数据预取和缓存策略

  1. 路由预取:预先加载可能访问的路由数据:
import { Link, useLocation } from 'react-router-dom';
import { useQueryClient } from 'react-query';

function NavLink({ to, prefetch, children }) {
  const queryClient = useQueryClient();
  const location = useLocation();
  
  return (
    <Link 
      to={to}
      onMouseEnter={() => {
        if (prefetch && to !== location.pathname) {
          // 预取路由数据
          queryClient.prefetchQuery(
            ['page-data', to],
            () => fetchPageData(to)
          );
        }
      }}
    >
      {children}
    </Link>
  );
}
  1. 无限加载与分页
import { useInfiniteQuery } from 'react-query';
import { useInView } from 'react-intersection-observer';
import { useEffect } from 'react';

function InfinitePostList() {
  const { ref, inView } = useInView();
  
  const {
    data,
    fetchNextPage,
    hasNextPage,
    isFetchingNextPage,
  } = useInfiniteQuery(
    'posts',
    ({ pageParam = 1 }) => fetchPosts(pageParam),
    {
      getNextPageParam: (lastPage) => 
        lastPage.nextPage || undefined,
    }
  );
  
  useEffect(() => {
    if (inView && hasNextPage && !isFetchingNextPage) {
      fetchNextPage();
    }
  }, [inView, hasNextPage, isFetchingNextPage, fetchNextPage]);
  
  return (
    <div>
      {data?.pages.map((page, i) => (
        <div key={i}>
          {page.posts.map(post => (
            <div key={post.id}>{post.title}</div>
          ))}
        </div>
      ))}
      
      <div ref={ref}>
        {isFetchingNextPage ? 'Loading more...' : null}
      </div>
    </div>
  );
}

# 性能分析与监控

# 使用React DevTools分析

  1. Profiler:记录和分析组件的渲染时间:

    • 使用Chrome DevTools中的React Profiler标签
    • 点击"记录"按钮,执行要测试的操作,然后停止记录
    • 分析渲染次数、渲染时间和渲染原因
  2. Highlight Updates:可视化组件的重新渲染:

    • 在React DevTools中启用"Highlight Updates"
    • 与应用交互,观察哪些组件在重新渲染

# 使用Performance API测量

import { useEffect, useState } from 'react';

function PerformanceMonitor() {
  const [metrics, setMetrics] = useState({});
  
  useEffect(() => {
    if ('performance' in window && 'getEntriesByType' in performance) {
      // 获取关键性能指标
      const navigationEntries = performance.getEntriesByType('navigation')[0];
      const paintEntries = performance.getEntriesByType('paint');
      
      const fpEntry = paintEntries.find(entry => entry.name === 'first-paint');
      const fcpEntry = paintEntries.find(entry => entry.name === 'first-contentful-paint');
      
      setMetrics({
        // 从导航开始到响应结束的时间
        responseEnd: navigationEntries.responseEnd,
        // 从导航开始到DOM内容加载事件的时间
        domContentLoaded: navigationEntries.domContentLoadedEventEnd,
        // 从导航开始到加载事件的时间
        loadComplete: navigationEntries.loadEventEnd,
        // 首次绘制时间
        firstPaint: fpEntry ? fpEntry.startTime : null,
        // 首次内容绘制时间
        firstContentfulPaint: fcpEntry ? fcpEntry.startTime : null,
      });
    }
  }, []);
  
  return (
    <div>
      <h2>Performance Metrics</h2>
      <ul>
        {Object.entries(metrics).map(([key, value]) => (
          <li key={key}>
            {key}: {value ? `${value.toFixed(2)}ms` : 'N/A'}
          </li>
        ))}
      </ul>
    </div>
  );
}

# 使用Web Vitals监控用户体验

import { useEffect } from 'react';
import { getCLS, getFID, getLCP, getTTFB, getFCP } from 'web-vitals';

function WebVitalsReporter() {
  useEffect(() => {
    function sendToAnalytics(metric) {
      // 将指标发送到分析服务
      console.log(metric.name, metric.value);
      
      // 实际应用中,使用真实的分析服务
      // analytics.send({
      //   name: metric.name,
      //   value: metric.value,
      //   id: metric.id,
      // });
    }
    
    // 监控核心Web Vitals和其他指标
    getCLS(sendToAnalytics); // 累积布局偏移
    getFID(sendToAnalytics); // 首次输入延迟
    getLCP(sendToAnalytics); // 最大内容绘制
    getTTFB(sendToAnalytics); // 首字节时间
    getFCP(sendToAnalytics); // 首次内容绘制
  }, []);
  
  return null; // 这个组件不渲染任何UI
}

// 在应用根组件中使用
function App() {
  return (
    <>
      <WebVitalsReporter />
      {/* 应用内容 */}
    </>
  );
}

# 服务端渲染(SSR)与静态生成(SSG)

# Next.js性能优化

Next.js提供了多种优化方式:

  1. 自动图像优化
import Image from 'next/image';

function ProductImage({ product }) {
  return (
    <Image
      src={product.image}
      alt={product.name}
      width={300}
      height={200}
      placeholder="blur" // 使用模糊占位符
      blurDataURL={product.blurDataUrl}
      priority={product.featured} // 关键图像优先加载
    />
  );
}
  1. 脚本优化
import Script from 'next/script';

function AnalyticsPage() {
  return (
    <div>
      <Script
        src="https://example.com/analytics.js"
        strategy="lazyOnload" // 延迟加载非关键脚本
        onLoad={() => console.log('Analytics script loaded')}
      />
      <main>
        {/* 页面内容 */}
      </main>
    </div>
  );
}
  1. ISR(增量静态再生成)
// pages/products/[id].js
export async function getStaticPaths() {
  // 预渲染最热门的产品
  const popularProducts = await getPopularProducts();
  
  return {
    paths: popularProducts.map(product => ({
      params: { id: product.id.toString() }
    })),
    fallback: 'blocking' // 对未预渲染的路径使用SSR
  };
}

export async function getStaticProps({ params }) {
  const product = await getProduct(params.id);
  
  return {
    props: { product },
    revalidate: 60 * 60, // 每小时重新生成一次
  };
}

function ProductPage({ product }) {
  return (
    <div>
      <h1>{product.name}</h1>
      <p>{product.description}</p>
      <Image
        src={product.image}
        alt={product.name}
        width={500}
        height={350}
      />
    </div>
  );
}

# 最佳实践总结

# 渲染优化核心原则

  1. 最小化状态更新范围:保持状态尽可能局部化
  2. 避免不必要的重新渲染:使用React.memouseMemouseCallback
  3. 推迟低优先级更新:使用useTransitionuseDeferredValue
  4. 细粒度组件拆分:不要让大型组件承担过多责任

# 性能优化检查清单

  • [ ] 使用React DevTools Profiler分析渲染性能
  • [ ] 识别并消除不必要的重新渲染
  • [ ] 优化列表渲染,考虑使用虚拟化
  • [ ] 缓存复杂计算结果和回调函数
  • [ ] 代码分割,延迟加载非关键组件
  • [ ] 优化图像和媒体资源
  • [ ] 实现数据预取和缓存
  • [ ] 考虑服务端渲染或静态生成
  • [ ] 监控和分析真实用户性能
  • [ ] 使用生产版本构建应用

# 常见性能反模式

避免以下常见的性能反模式:

  1. 过度优化:不要在没有性能问题的地方进行优化
  2. 忽略依赖数组:不正确的依赖数组会导致bug或性能问题
  3. 过早优化:先编写清晰代码,然后根据需要优化
  4. 不必要的状态:派生状态应计算,而不是存储
  5. 组件过大:大型组件更难优化,应拆分为小型组件

# 性能优化案例研究

# 电商产品列表优化

一个典型的电商产品列表优化案例:

import { useState, useMemo, useCallback, useTransition } from 'react';
import { FixedSizeList } from 'react-window';
import { useQuery } from 'react-query';

function ProductsList() {
  const [filters, setFilters] = useState({
    category: 'all',
    minPrice: 0,
    maxPrice: 1000,
    sortBy: 'popularity'
  });
  
  const [searchTerm, setSearchTerm] = useState('');
  const [isPending, startTransition] = useTransition();
  
  // 使用React Query获取并缓存数据
  const { data: products = [], isLoading } = useQuery(
    ['products', filters],
    () => fetchProducts(filters),
    { keepPreviousData: true }
  );
  
  // 处理搜索,使用防抖减少状态更新
  const handleSearch = useCallback((e) => {
    const value = e.target.value;
    setSearchTerm(value); // 立即更新输入框
    
    startTransition(() => {
      // 标记为低优先级更新
      setFilters(f => ({ ...f, search: value }));
    });
  }, []);
  
  // 使用记忆化处理筛选逻辑
  const filteredProducts = useMemo(() => {
    if (!searchTerm) return products;
    
    return products.filter(product =>
      product.name.toLowerCase().includes(searchTerm.toLowerCase())
    );
  }, [products, searchTerm]);
  
  // 列表项渲染器
  const Row = useCallback(({ index, style }) => {
    const product = filteredProducts[index];
    return (
      <div style={style} className="product-item">
        <img 
          src={product.thumbnailUrl} 
          alt={product.name} 
          loading="lazy" 
        />
        <h3>{product.name}</h3>
        <p>${product.price}</p>
      </div>
    );
  }, [filteredProducts]);
  
  if (isLoading) return <div>Loading products...</div>;
  
  return (
    <div className="products-page">
      <div className="filters">
        <input
          type="text"
          value={searchTerm}
          onChange={handleSearch}
          placeholder="Search products..."
        />
        {/* 其他筛选器 */}
      </div>
      
      {isPending && <div>Updating results...</div>}
      
      <div className="products-list">
        <FixedSizeList
          height={800}
          width="100%"
          itemCount={filteredProducts.length}
          itemSize={200}
        >
          {Row}
        </FixedSizeList>
      </div>
    </div>
  );
}

# 总结

React性能优化是一个多层次的过程,涵盖从组件级别优化到应用架构优化。关键是识别瓶颈,应用适当的技术,并持续监控性能。

通过合理使用React提供的API(如React.memouseMemouseCallback),优化数据结构和算法,以及利用现代工具(如代码分割、缓存和服务端渲染),可以构建出高性能、响应迅速的React应用。

最后,记住性能优化是一个持续的过程,应该基于真实的用户体验和测量数据进行,而不是基于假设或过早优化。