实用指南:React基础到进阶

React 全面深入解析:从基础到高级实战指南

一、React 的基础知识

1. 什么是 React?

React 是由 Facebook 开发并开源的一个用于构建用户界面的 JavaScript 库。自 2013 年发布以来,React 已经发展成为前端开发领域最受欢迎的技术之一。与传统的前端开发框架(如 Angular、Vue)不同,React 的核心思想是​​组件化开发​​。

React 的核心特点:
  • ​声明式编程​​:React 采用声明式范式,让代码更加可预测且易于调试

  • ​组件化架构​​:将复杂的 UI 拆分为独立、可复用的组件

  • ​虚拟 DOM​​:通过高效的差异算法优化性能

  • ​单向数据流​​:数据自上而下流动,保证应用状态的可预测性

  • ​Learn Once, Write Anywhere​​:React 可以用于 Web、移动端(React Native)、VR 等场景

React 的发展历程:
  • 2013 年:React 首次发布,引入 JSX 和虚拟 DOM 概念

  • 2015 年:React Native 发布,扩展至移动端开发

  • 2018 年:React 16.3 引入新的生命周期方法

  • 2019 年:React 16.8 推出 Hooks,彻底改变函数组件的开发方式

  • 2020 年:React 17 作为过渡版本,为未来特性做准备

  • 2022 年:React 18 发布,引入并发特性

2. React 的基本概念

a. 组件(Components)

组件是 React 应用的构建块,每个组件都封装了自己的结构、样式和行为。

​类组件(Class Components)​​:

import React, { Component } from 'react';
class Welcome extends Component {
  constructor(props) {
    super(props);
    this.state = {
      message: 'Hello, World!'
    };
  }
  componentDidMount() {
    console.log('组件已挂载');
  }
  render() {
    return 

{this.state.message}

; } } export default Welcome;

​函数组件(Function Components)​​:

import React from 'react';
function Welcome(props) {
  return 

Hello, {props.name}!

; } // 或使用箭头函数 const Welcome = (props) => { return

Hello, {props.name}!

; }; export default Welcome;
b. JSX(JavaScript XML)

JSX 是 React 的核心语法扩展,它允许我们在 JavaScript 中编写类似 HTML 的代码。

​JSX 的基本规则​​:

// 1. 必须有一个根元素
const element = (
  

标题

段落

); // 2. 使用 className 代替 class const element =
内容
; // 3. 使用驼峰命名法定义属性 const element = ; // 4. 必须闭合所有标签 const element = 描述; // 5. 在 JSX 中嵌入 JavaScript 表达式 const name = '张三'; const element =

Hello, {name}!

; // 6. 条件渲染 const element = (
{isLoggedIn ? : }
); // 7. 列表渲染 const numbers = [1, 2, 3, 4, 5]; const listItems = numbers.map((number) =>
  • {number}
  • );
    c. 虚拟 DOM(Virtual DOM)

    虚拟 DOM 是 React 性能优化的核心机制,它通过以下步骤工作:

    1. ​生成虚拟 DOM​​:当组件状态变化时,React 会重新生成整个 UI 的虚拟 DOM 表示

    2. ​差异比较(Diffing)​​:React 比较新旧虚拟 DOM 的差异

    3. ​最小化更新​​:只更新实际 DOM 中发生变化的部分

    // 虚拟 DOM 的工作原理示例
    class Counter extends Component {
      state = { count: 0 };
      handleClick = () => {
        this.setState({ count: this.state.count + 1 });
      };
      render() {
        return (
          

    计数: {this.state.count}

    ); } }

    3. React 开发环境搭建

    使用 Create React App 创建项目
    # 安装 Create React App
    npm install -g create-react-app
    # 创建新项目
    npx create-react-app my-react-app
    # 进入项目目录
    cd my-react-app
    # 启动开发服务器
    npm start
    项目结构说明
    my-react-app/
    ├── public/
    │   ├── index.html
    │   └── favicon.ico
    ├── src/
    │   ├── components/     # 组件目录
    │   ├── styles/        # 样式文件
    │   ├── utils/         # 工具函数
    │   ├── App.js         # 根组件
    │   ├── index.js       # 入口文件
    │   └── index.css      # 全局样式
    ├── package.json
    └── README.md

    二、React 的进阶概念

    1. 状态(State)和属性(Props)

    State 的深入理解

    ​类组件中的 State​​:

    class Counter extends Component {
      constructor(props) {
        super(props);
        // 初始化状态
        this.state = {
          count: 0,
          isActive: true
        };
      }
      // 正确更新状态的方式
      increment = () => {
        this.setState(prevState => ({
          count: prevState.count + 1
        }));
      };
      // 批量更新
      handleMultipleUpdates = () => {
        this.setState({ count: 1 });
        this.setState({ isActive: false });
        // 等同于
        this.setState({
          count: 1,
          isActive: false
        });
      };
      render() {
        return (
          

    当前计数: {this.state.count}

    状态: {this.state.isActive ? '活跃' : '非活跃'}

    ); } }

    ​函数组件中的 State(使用 useState Hook)​​:

    import React, { useState } from 'react';
    function Counter() {
      // 使用 useState 定义状态
      const [count, setCount] = useState(0);
      const [user, setUser] = useState({ name: '', age: 0 });
      // 更新对象状态
      const updateUser = () => {
        setUser(prevUser => ({
          ...prevUser,
          age: prevUser.age + 1
        }));
      };
      // 异步更新的注意事项
      const incrementTwice = () => {
        setCount(count + 1);
        setCount(count + 1); // 这里不会立即更新,还是基于原来的 count
        // 正确的方式
        setCount(prevCount => prevCount + 1);
        setCount(prevCount => prevCount + 1);
      };
      return (
        

    计数: {count}

    ); }
    Props 的深入理解

    ​Props 的基本使用​​:

    // 父组件
    function App() {
      const user = { name: '张三', age: 25 };
      const numbers = [1, 2, 3, 4, 5];
      return (
        
    console.log('用户登录')} />
    ); } // 子组件 - 函数组件 function UserCard(props) { return (

    {props.name}

    年龄: {props.age}

    {props.isVerified && 已验证}
    ); } // 子组件 - 使用解构赋值 function NumberList({ numbers, title = "数字列表" }) { return (

    {title}

      {numbers.map(num => (
    • {num}
    • ))}
    ); } // Props 的默认值 NumberList.defaultProps = { title: "默认标题" }; // Props 的类型检查 import PropTypes from 'prop-types'; NumberList.propTypes = { numbers: PropTypes.array.isRequired, title: PropTypes.string };

    ​Props 的高级用法​​:

    // Children 属性
    function Container({ children, className }) {
      return 
    {children}
    ; } function App() { return (

    标题

    内容

    ); } // 渲染属性模式(Render Props) class DataProvider extends Component { state = { data: null, loading: true }; componentDidMount() { fetch('/api/data') .then(response => response.json()) .then(data => this.setState({ data, loading: false })); } render() { return this.props.children(this.state); } } // 使用 {({ data, loading }) => ( loading ?
    加载中...
    :
    {data}
    )}

    2. 生命周期方法(Lifecycle Methods)

    类组件的生命周期
    class LifecycleDemo extends Component {
      constructor(props) {
        super(props);
        this.state = { count: 0 };
        console.log('1. constructor - 构造函数');
      }
      static getDerivedStateFromProps(props, state) {
        console.log('2. getDerivedStateFromProps - 从 props 派生状态');
        return null;
      }
      componentDidMount() {
        console.log('4. componentDidMount - 组件挂载完成');
        // 适合进行数据获取、订阅事件等操作
      }
      shouldComponentUpdate(nextProps, nextState) {
        console.log('5. shouldComponentUpdate - 是否应该更新');
        return true; // 返回 false 可以阻止重新渲染
      }
      getSnapshotBeforeUpdate(prevProps, prevState) {
        console.log('6. getSnapshotBeforeUpdate - 获取更新前的快照');
        return null;
      }
      componentDidUpdate(prevProps, prevState, snapshot) {
        console.log('7. componentDidUpdate - 组件更新完成');
        // 适合在更新后执行操作
      }
      componentWillUnmount() {
        console.log('8. componentWillUnmount - 组件即将卸载');
        // 清理工作:取消订阅、清除定时器等
      }
      handleClick = () => {
        this.setState({ count: this.state.count + 1 });
      };
      render() {
        console.log('3. render - 渲染');
        return (
          

    计数: {this.state.count}

    ); } }
    生命周期图示
    挂载阶段:
    constructor → getDerivedStateFromProps → render → componentDidMount
    更新阶段:
    getDerivedStateFromProps → shouldComponentUpdate → render → getSnapshotBeforeUpdate → componentDidUpdate
    卸载阶段:
    componentWillUnmount

    3. 钩子(Hooks)

    Hooks 是 React 16.8 引入的革命性特性,让函数组件能够使用状态和其他 React 特性。

    基础 Hooks

    ​useState​​:

    import React, { useState } from 'react';
    function Example() {
      // 基本类型状态
      const [count, setCount] = useState(0);
      // 对象类型状态
      const [user, setUser] = useState({
        name: '',
        email: '',
        age: 0
      });
      // 数组类型状态
      const [items, setItems] = useState([]);
      // 更新对象状态
      const updateUser = (field, value) => {
        setUser(prevUser => ({
          ...prevUser,
          [field]: value
        }));
      };
      // 更新数组状态
      const addItem = (item) => {
        setItems(prevItems => [...prevItems, item]);
      };
      return (
        

    计数: {count}

    updateUser('name', e.target.value)} placeholder="姓名" />
    ); }

    ​useEffect​​:

    import React, { useState, useEffect } from 'react';
    function DataFetcher() {
      const [data, setData] = useState(null);
      const [loading, setLoading] = useState(true);
      const [userId, setUserId] = useState(1);
      // 1. 无依赖数组 - 每次渲染后都执行
      useEffect(() => {
        console.log('组件渲染完成');
      });
      // 2. 空依赖数组 - 仅在挂载时执行一次
      useEffect(() => {
        console.log('组件挂载完成');
        // 清理函数
        return () => {
          console.log('组件即将卸载');
        };
      }, []);
      // 3. 有依赖数组 - 依赖变化时执行
      useEffect(() => {
        const fetchData = async () => {
          setLoading(true);
          try {
            const response = await fetch(`/api/users/${userId}`);
            const userData = await response.json();
            setData(userData);
          } catch (error) {
            console.error('获取数据失败:', error);
          } finally {
            setLoading(false);
          }
        };
        fetchData();
        // 清理函数:取消请求或清理副作用
        return () => {
          // 取消请求的逻辑
        };
      }, [userId]); // 依赖数组
      if (loading) return 
    加载中...
    ; return (

    用户信息

    姓名: {data.name}

    ); }

    ​useContext​​:

    import React, { createContext, useContext, useState } from 'react';
    // 创建 Context
    const ThemeContext = createContext();
    const UserContext = createContext();
    // 提供者组件
    function App() {
      const [theme, setTheme] = useState('light');
      const [user, setUser] = useState({ name: '张三', role: 'admin' });
      return (
        
          
            
    ); } // 消费者组件 function Header() { const { theme, setTheme } = useContext(ThemeContext); const { user } = useContext(UserContext); const toggleTheme = () => { setTheme(theme === 'light' ? 'dark' : 'light'); }; return (

    欢迎, {user.name}

    ); } function MainContent() { const { theme } = useContext(ThemeContext); return (

    这是主要内容区域

    ); }
    高级 Hooks

    ​useReducer​​:

    import React, { useReducer } from 'react';
    // 初始状态
    const initialState = {
      count: 0,
      history: []
    };
    // Reducer 函数
    function counterReducer(state, action) {
      switch (action.type) {
        case 'INCREMENT':
          return {
            ...state,
            count: state.count + 1,
            history: [...state.history, { type: 'INCREMENT', value: state.count + 1 }]
          };
        case 'DECREMENT':
          return {
            ...state,
            count: state.count - 1,
            history: [...state.history, { type: 'DECREMENT', value: state.count - 1 }]
          };
        case 'RESET':
          return initialState;
        case 'SET_COUNT':
          return {
            ...state,
            count: action.payload,
            history: [...state.history, { type: 'SET', value: action.payload }]
          };
        default:
          return state;
      }
    }
    function Counter() {
      const [state, dispatch] = useReducer(counterReducer, initialState);
      return (
        

    当前计数: {state.count}

    操作历史:

      {state.history.map((entry, index) => (
    • {entry.type}: {entry.value}
    • ))}
    ); }

    ​useMemo 和 useCallback​​:

    import React, { useState, useMemo, useCallback } from 'react';
    function ExpensiveCalculation({ number }) {
      // 使用 useMemo 缓存计算结果
      const result = useMemo(() => {
        console.log('执行昂贵计算...');
        let sum = 0;
        for (let i = 0; i < number; i++) {
          sum += i;
        }
        return sum;
      }, [number]); // 只有当 number 变化时才重新计算
      return 
    计算结果: {result}
    ; } function UserList({ users, onUserClick }) { // 使用 useMemo 缓存过滤结果 const activeUsers = useMemo(() => { return users.filter(user => user.isActive); }, [users]); return (
      {activeUsers.map(user => (
    • onUserClick(user)}> {user.name}
    • ))}
    ); } function App() { const [count, setCount] = useState(0); const [users, setUsers] = useState([ { id: 1, name: '张三', isActive: true }, { id: 2, name: '李四', isActive: false }, { id: 3, name: '王五', isActive: true } ]); // 使用 useCallback 缓存函数 const handleUserClick = useCallback((user) => { console.log('用户被点击:', user.name); }, []); // 空依赖数组表示函数不会改变 const addUser = useCallback((name) => { setUsers(prevUsers => [ ...prevUsers, { id: Date.now(), name, isActive: true } ]); }, []); return (
    ); }

    ​自定义 Hooks​​:

    import { useState, useEffect } from 'react';
    // 自定义 Hook:数据获取
    function useFetch(url) {
      const [data, setData] = useState(null);
      const [loading, setLoading] = useState(true);
      const [error, setError] = useState(null);
      useEffect(() => {
        const fetchData = async () => {
          try {
            setLoading(true);
            const response = await fetch(url);
            if (!response.ok) {
              throw new Error('网络响应不正常');
            }
            const result = await response.json();
            setData(result);
          } catch (err) {
            setError(err.message);
          } finally {
            setLoading(false);
          }
        };
        fetchData();
      }, [url]);
      return { data, loading, error };
    }
    // 自定义 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(`读取 localStorage 键 "${key}" 时出错:`, error);
          return initialValue;
        }
      });
      const setValue = (value) => {
        try {
          setStoredValue(value);
          window.localStorage.setItem(key, JSON.stringify(value));
        } catch (error) {
          console.error(`设置 localStorage 键 "${key}" 时出错:`, error);
        }
      };
      return [storedValue, setValue];
    }
    // 使用自定义 Hooks
    function UserProfile({ userId }) {
      const { data: user, loading, error } = useFetch(`/api/users/${userId}`);
      const [theme, setTheme] = useLocalStorage('theme', 'light');
      if (loading) return 
    加载中...
    ; if (error) return
    错误: {error}
    ; return (

    {user.name}

    邮箱: {user.email}

    ); }

    4. 事件处理(Event Handling)

    function EventHandling() {
      const [form, setForm] = useState({
        username: '',
        password: '',
        rememberMe: false
      });
      // 基本事件处理
      const handleClick = (event) => {
        event.preventDefault();
        console.log('按钮被点击了', event);
      };
      // 输入处理
      const handleInputChange = (event) => {
        const { name, value, type, checked } = event.target;
        setForm(prevForm => ({
          ...prevForm,
          [name]: type === 'checkbox' ? checked : value
        }));
      };
      // 表单提交
      const handleSubmit = (event) => {
        event.preventDefault();
        console.log('表单提交:', form);
      };
      // 键盘事件
      const handleKeyPress = (event) => {
        if (event.key === 'Enter') {
          console.log('Enter 键被按下');
        }
      };
      // 合成事件池(React 17 之前)
      const handleEventPool = (event) => {
        // React 17 之前需要持久化事件对象
        event.persist();
        setTimeout(() => {
          console.log(event.type);
        }, 1000);
      };
      return (
        
    ); }

    三、React 的高级应用

    1. 状态管理(State Management)

    a. Redux 状态管理

    ​Redux 基础设置​​:

    // store.js
    import { createStore, combineReducers, applyMiddleware } from 'redux';
    import { composeWithDevTools } from 'redux-devtools-extension';
    import thunk from 'redux-thunk';
    // Action Types
    const INCREMENT = 'INCREMENT';
    const DECREMENT = 'DECREMENT';
    const SET_USER = 'SET_USER';
    // Action Creators
    export const increment = () => ({ type: INCREMENT });
    export const decrement = () => ({ type: DECREMENT });
    export const setUser = (user) => ({ type: SET_USER, payload: user });
    // 异步 Action
    export const fetchUser = (userId) => {
      return async (dispatch) => {
        try {
          const response = await fetch(`/api/users/${userId}`);
          const user = await response.json();
          dispatch(setUser(user));
        } catch (error) {
          console.error('获取用户失败:', error);
        }
      };
    };
    // Reducers
    const counterReducer = (state = 0, action) => {
      switch (action.type) {
        case INCREMENT:
          return state + 1;
        case DECREMENT:
          return state - 1;
        default:
          return state;
      }
    };
    const userReducer = (state = null, action) => {
      switch (action.type) {
        case SET_USER:
          return action.payload;
        default:
          return state;
      }
    };
    const rootReducer = combineReducers({
      counter: counterReducer,
      user: userReducer
    });
    // 创建 Store
    const store = createStore(
      rootReducer,
      composeWithDevTools(applyMiddleware(thunk))
    );
    export default store;

    ​React-Redux 连接​​:

    // index.js
    import React from 'react';
    import ReactDOM from 'react-dom';
    import { Provider } from 'react-redux';
    import store from './store';
    import App from './App';
    ReactDOM.render(
      
        
      ,
      document.getElementById('root')
    );
    // Counter.js
    import React from 'react';
    import { connect } from 'react-redux';
    import { increment, decrement } from './store';
    function Counter({ count, increment, decrement }) {
      return (
        

    计数: {count}

    ); } const mapStateToProps = (state) => ({ count: state.counter }); const mapDispatchToProps = { increment, decrement }; export default connect(mapStateToProps, mapDispatchToProps)(Counter);

    ​Redux Toolkit(现代 Redux)​​:

    // store.js
    import { configureStore, createSlice } from '@reduxjs/toolkit';
    const counterSlice = createSlice({
      name: 'counter',
      initialState: 0,
      reducers: {
        increment: (state) => state + 1,
        decrement: (state) => state - 1,
        incrementByAmount: (state, action) => state + action.payload
      }
    });
    const userSlice = createSlice({
      name: 'user',
      initialState: null,
      reducers: {
        setUser: (state, action) => action.payload,
        clearUser: () => null
      }
    });
    export const { increment, decrement, incrementByAmount } = counterSlice.actions;
    export const { setUser, clearUser } = userSlice.actions;
    const store = configureStore({
      reducer: {
        counter: counterSlice.reducer,
        user: userSlice.reducer
      }
    });
    export default store;
    // 在组件中使用
    import React from 'react';
    import { useSelector, useDispatch } from 'react-redux';
    import { increment, decrement } from './store';
    function Counter() {
      const count = useSelector(state => state.counter);
      const dispatch = useDispatch();
      return (
        

    计数: {count}

    ); }
    b. Context API 状态管理

    ​创建 Context​​:

    // contexts/AppContext.js
    import React, { createContext, useContext, useReducer } from 'react';
    const AppContext = createContext();
    // 初始状态
    const initialState = {
      user: null,
      theme: 'light',
      notifications: [],
      loading: false
    };
    // Reducer 函数
    function appReducer(state, action) {
      switch (action.type) {
        case 'SET_USER':
          return { ...state, user: action.payload };
        case 'SET_THEME':
          return { ...state, theme: action.payload };
        case 'ADD_NOTIFICATION':
          return {
            ...state,
            notifications: [...state.notifications, action.payload]
          };
        case 'SET_LOADING':
          return { ...state, loading: action.payload };
        default:
          return state;
      }
    }
    // Provider 组件
    export function AppProvider({ children }) {
      const [state, dispatch] = useReducer(appReducer, initialState);
      // Action creators
      const setUser = (user) => dispatch({ type: 'SET_USER', payload: user });
      const setTheme = (theme) => dispatch({ type: 'SET_THEME', payload: theme });
      const addNotification = (message) =>
        dispatch({ type: 'ADD_NOTIFICATION', payload: { id: Date.now(), message } });
      const setLoading = (loading) => dispatch({ type: 'SET_LOADING', payload: loading });
      const value = {
        ...state,
        setUser,
        setTheme,
        addNotification,
        setLoading
      };
      return (
        
          {children}
        
      );
    }
    // 自定义 Hook
    export function useApp() {
      const context = useContext(AppContext);
      if (!context) {
        throw new Error('useApp 必须在 AppProvider 内部使用');
      }
      return context;
    }

    ​使用 Context​​:

    // App.js
    import React from 'react';
    import { AppProvider } from './contexts/AppContext';
    import Header from './components/Header';
    import MainContent from './components/MainContent';
    import NotificationCenter from './components/NotificationCenter';
    function App() {
      return (
        
          
    ); } // Header.js import React from 'react'; import { useApp } from '../contexts/AppContext'; function Header() { const { user, theme, setTheme } = useApp(); const toggleTheme = () => { setTheme(theme === 'light' ? 'dark' : 'light'); }; return (

    我的应用

    {user && 欢迎, {user.name}}
    ); }

    2. 路由(Routing)

    ​React Router 基础​​:

    // App.js
    import React from 'react';
    import { BrowserRouter as Router, Routes, Route, Link } from 'react-router-dom';
    import Home from './pages/Home';
    import About from './pages/About';
    import User from './pages/User';
    import NotFound from './pages/NotFound';
    function App() {
      return (
        
          
          
            } />
            } />
            } />
            } />
          
        
      );
    }
    // User.js
    import React from 'react';
    import { useParams, useNavigate, useLocation } from 'react-router-dom';
    function User() {
      const { id } = useParams();
      const navigate = useNavigate();
      const location = useLocation();
      const goBack = () => {
        navigate(-1); // 返回上一页
      };
      const goToAbout = () => {
        navigate('/about', { replace: true }); // 替换当前历史记录
      };
      return (
        

    用户页面

    用户ID: {id}

    当前路径: {location.pathname}

    ); }

    ​路由保护​​:

    // ProtectedRoute.js
    import React from 'react';
    import { Navigate, useLocation } from 'react-router-dom';
    import { useAuth } from '../contexts/AuthContext';
    function ProtectedRoute({ children }) {
      const { user, loading } = useAuth();
      const location = useLocation();
      if (loading) {
        return 
    加载中...
    ; } if (!user) { // 重定向到登录页面,并保存当前路径 return ; } return children; } // 使用 } />

    3. 异步数据处理

    ​数据获取模式​​:

    import React, { useState, useEffect } from 'react';
    function DataFetching() {
      const [data, setData] = useState(null);
      const [loading, setLoading] = useState(true);
      const [error, setError] = useState(null);
      useEffect(() => {
        const fetchData = async () => {
          try {
            setLoading(true);
            setError(null);
            const response = await fetch('/api/data');
            if (!response.ok) {
              throw new Error(`HTTP error! status: ${response.status}`);
            }
            const result = await response.json();
            setData(result);
          } catch (err) {
            setError(err.message);
          } finally {
            setLoading(false);
          }
        };
        fetchData();
      }, []); // 空依赖数组表示只在挂载时执行
      if (loading) return 
    加载中...
    ; if (error) return
    错误: {error}
    ; if (!data) return
    暂无数据
    ; return (

    数据列表

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

    ​优化数据获取​​:

    import React, { useState, useEffect, useRef } from 'react';
    function OptimizedDataFetching() {
      const [data, setData] = useState(null);
      const [loading, setLoading] = useState(false);
      const [error, setError] = useState(null);
      const abortControllerRef = useRef(null);
      useEffect(() => {
        return () => {
          // 组件卸载时中止请求
          if (abortControllerRef.current) {
            abortControllerRef.current.abort();
          }
        };
      }, []);
      const fetchData = async (url) => {
        if (abortControllerRef.current) {
          abortControllerRef.current.abort(); // 中止之前的请求
        }
        abortControllerRef.current = new AbortController();
        try {
          setLoading(true);
          setError(null);
          const response = await fetch(url, {
            signal: abortControllerRef.current.signal
          });
          if (!response.ok) throw new Error('请求失败');
          const result = await response.json();
          setData(result);
        } catch (err) {
          if (err.name !== 'AbortError') {
            setError(err.message);
          }
        } finally {
          setLoading(false);
          abortControllerRef.current = null;
        }
      };
      return (
        
    {loading &&
    加载中...
    } {/* 渲染数据 */}
    ); }

    4. 性能优化(Performance Optimization)

    ​React.memo​​:

    import React, { memo } from 'react';
    // 普通组件 - 每次父组件渲染都会重新渲染
    function UserItem({ user, onEdit }) {
      console.log('UserItem 渲染:', user.id);
      return (
        
  • {user.name}
  • ); } // 使用 memo 包装的组件 - 只有 props 变化时才会重新渲染 const OptimizedUserItem = memo(UserItem, (prevProps, nextProps) => { // 自定义比较函数 return prevProps.user.id === nextProps.user.id && prevProps.onEdit === nextProps.onEdit; }); // 使用 useCallback 优化函数引用 function UserList() { const [users, setUsers] = useState([]); const [selectedUser, setSelectedUser] = useState(null); // 使用 useCallback 缓存函数,避免不必要的重新渲染 const handleEdit = useCallback((user) => { setSelectedUser(user); }, []); return (
    {users.map(user => ( ))}
    ); }

    ​useMemo 优化复杂计算​​:

    import React, { useMemo } from 'react';
    function ExpensiveComponent({ data, filter }) {
      // 使用 useMemo 缓存计算结果
      const filteredData = useMemo(() => {
        console.log('执行过滤计算...');
        return data.filter(item =>
          item.name.toLowerCase().includes(filter.toLowerCase())
        );
      }, [data, filter]); // 只有当 data 或 filter 变化时才重新计算
      // 另一个使用 useMemo 的例子:配置对象
      const config = useMemo(() => ({
        maxItems: 10,
        theme: 'dark',
        onItemClick: () => console.log('项目被点击')
      }), []); // 空依赖数组表示这个对象永远不会改变
      return (
        

    过滤结果 ({filteredData.length} 项)

      {filteredData.map(item => (
    • {item.name}
    • ))}
    ); }

    ​代码分割(懒加载)​​:

    import React, { lazy, Suspense } from 'react';
    // 使用 lazy 进行代码分割
    const LazyComponent = lazy(() => import('./LazyComponent'));
    const AnotherLazyComponent = lazy(() => import('./AnotherLazyComponent'));
    function App() {
      const [showLazy, setShowLazy] = useState(false);
      return (
        
    {showLazy && ( 加载中...
    }> )}
    ); } // 路由级别的代码分割 const Home = lazy(() => import('./pages/Home')); const About = lazy(() => import('./pages/About')); function App() { return ( 页面加载中...}> } /> } /> ); }

    四、实际应用案例

    1. 完整的 Todo 应用

    import React, { useState, useReducer, useMemo, useCallback } from 'react';
    // Reducer 函数
    function todoReducer(state, action) {
      switch (action.type) {
        case 'ADD_TODO':
          return {
            ...state,
            todos: [...state.todos, {
              id: Date.now(),
              text: action.payload,
              completed: false,
              createdAt: new Date().toISOString()
            }]
          };
        case 'TOGGLE_TODO':
          return {
            ...state,
            todos: state.todos.map(todo =>
              todo.id === action.payload
                ? { ...todo, completed: !todo.completed }
                : todo
            )
          };
        case 'DELETE_TODO':
          return {
            ...state,
            todos: state.todos.filter(todo => todo.id !== action.payload)
          };
        case 'EDIT_TODO':
          return {
            ...state,
            todos: state.todos.map(todo =>
              todo.id === action.payload.id
                ? { ...todo, text: action.payload.text }
                : todo
            )
          };
        case 'SET_FILTER':
          return {
            ...state,
            filter: action.payload
          };
        default:
          return state;
      }
    }
    // 初始状态
    const initialState = {
      todos: [],
      filter: 'all' // all, active, completed
    };
    function TodoApp() {
      const [state, dispatch] = useReducer(todoReducer, initialState);
      const [inputValue, setInputValue] = useState('');
      const [editingId, setEditingId] = useState(null);
      const [editText, setEditText] = useState('');
      // 添加待办事项
      const addTodo = useCallback(() => {
        if (inputValue.trim()) {
          dispatch({ type: 'ADD_TODO', payload: inputValue.trim() });
          setInputValue('');
        }
      }, [inputValue]);
      // 切换完成状态
      const toggleTodo = useCallback((id) => {
        dispatch({ type: 'TOGGLE_TODO', payload: id });
      }, []);
      // 删除待办事项
      const deleteTodo = useCallback((id) => {
        dispatch({ type: 'DELETE_TODO', payload: id });
      }, []);
      // 开始编辑
      const startEdit = useCallback((todo) => {
        setEditingId(todo.id);
        setEditText(todo.text);
      }, []);
      // 保存编辑
      const saveEdit = useCallback(() => {
        if (editText.trim()) {
          dispatch({
            type: 'EDIT_TODO',
            payload: { id: editingId, text: editText.trim() }
          });
          setEditingId(null);
          setEditText('');
        }
      }, [editText, editingId]);
      // 取消编辑
      const cancelEdit = useCallback(() => {
        setEditingId(null);
        setEditText('');
      }, []);
      // 过滤待办事项
      const filteredTodos = useMemo(() => {
        switch (state.filter) {
          case 'active':
            return state.todos.filter(todo => !todo.completed);
          case 'completed':
            return state.todos.filter(todo => todo.completed);
          default:
            return state.todos;
        }
      }, [state.todos, state.filter]);
      // 统计信息
      const stats = useMemo(() => {
        const total = state.todos.length;
        const completed = state.todos.filter(todo => todo.completed).length;
        const active = total - completed;
        return { total, completed, active };
      }, [state.todos]);
      return (
        

    Todo 应用

    {/* 添加新待办事项 */}
    setInputValue(e.target.value)} onKeyPress={(e) => e.key === 'Enter' && addTodo()} placeholder="添加新的待办事项..." />
    {/* 过滤选项 */}
    {/* 待办事项列表 */}
      {filteredTodos.map(todo => (
    • {editingId === todo.id ? ( // 编辑模式
      setEditText(e.target.value)} onKeyPress={(e) => { if (e.key === 'Enter') saveEdit(); if (e.key === 'Escape') cancelEdit(); }} autoFocus />
      ) : ( // 查看模式
      toggleTodo(todo.id)} /> startEdit(todo)} > {todo.text}
      )}
    • ))}
    {/* 空状态 */} {filteredTodos.length === 0 && (
    {state.filter === 'all' && '暂无待办事项'} {state.filter === 'active' && '暂无待完成的待办事项'} {state.filter === 'completed' && '暂无已完成的待办事项'}
    )}
    ); } export default TodoApp;

    2. 数据可视化仪表板

    import React, { useState, useEffect, useMemo } from 'react';
    import { useFetch } from '../hooks/useFetch';
    function Dashboard() {
      const [timeRange, setTimeRange] = useState('week');
      const { data: stats, loading, error } = useFetch(`/api/stats?range=${timeRange}`);
      // 处理图表数据
      const chartData = useMemo(() => {
        if (!stats) return null;
        return {
          labels: stats.chartData.labels,
          datasets: [
            {
              label: '用户活跃度',
              data: stats.chartData.values,
              backgroundColor: 'rgba(54, 162, 235, 0.2)',
              borderColor: 'rgba(54, 162, 235, 1)',
              borderWidth: 2
            }
          ]
        };
      }, [stats]);
      if (loading) return 
    加载中...
    ; if (error) return
    错误: {error}
    ; if (!stats) return
    暂无数据
    ; return (

    数据仪表板

    用户活跃趋势

    {/* 这里可以集成 Chart.js 或其他图表库 */}
    {/* 实际项目中这里会渲染真实的图表 */}

    图表组件占位符

    {JSON.stringify(chartData, null, 2)}
    ); } function StatCard({ title, value, change, icon }) { const isPositive = change >= 0; return (
    {icon} {title}
    {value}
    {isPositive ? '↑' : '↓'} {Math.abs(change)}%
    ); } export default Dashboard;

    五、React 最佳实践和常见模式

    1. 组件设计原则

    ​单一职责原则​​:

    // 不好的做法:一个组件做太多事情
    function UserProfile() {
      // 这个组件同时处理用户信息、设置、历史记录...
      return 
    ...
    ; } // 好的做法:拆分为专注的组件 function UserProfile() { return (
    ); } function UserInfo({ user }) { return (
    {user.name}

    {user.name}

    {user.bio}

    ); }

    ​组合优于继承​​:

    // 使用组合模式
    function Card({ children, className }) {
      return 
    {children}
    ; } function UserCard({ user }) { return (

    {user.name}

    {user.email}

    ); } function ProductCard({ product }) { return (

    {product.name}

    ${product.price}

    ); }

    2. 错误边界(Error Boundaries)

    import React from 'react';
    class ErrorBoundary extends React.Component {
      constructor(props) {
        super(props);
        this.state = { hasError: false, error: null, errorInfo: null };
      }
      static getDerivedStateFromError(error) {
        return { hasError: true };
      }
      componentDidCatch(error, errorInfo) {
        this.setState({
          error: error,
          errorInfo: errorInfo
        });
        // 可以在这里记录错误到错误报告服务
        console.error('错误边界捕获到错误:', error, errorInfo);
      }
      render() {
        if (this.state.hasError) {
          return (
            

    出了点问题。

    {this.state.error && this.state.error.toString()}
    {this.state.errorInfo.componentStack}
    ); } return this.props.children; } } // 使用 function App() { return ( ); }

    3. 测试策略

    // MyComponent.js
    import React from 'react';
    function MyComponent({ onClick, value }) {
      return (
        
    {value}
    ); } export default MyComponent; // MyComponent.test.js import React from 'react'; import { render, screen, fireEvent } from '@testing-library/react'; import '@testing-library/jest-dom'; import MyComponent from './MyComponent'; test('渲染组件并显示正确的值', () => { render(); expect(screen.getByTestId('value')).toHaveTextContent('测试值'); }); test('点击按钮时调用 onClick', () => { const handleClick = jest.fn(); render(); fireEvent.click(screen.getByText('点击我')); expect(handleClick).toHaveBeenCalledTimes(1); });

    六、React 18 新特性

    1. 并发特性(Concurrent Features)

    import React, { useState, Suspense, useTransition } from 'react';
    function SearchResults({ query }) {
      if (query === '') {
        return null;
      }
      // 模拟数据加载
      const results = use(fetchResults(query));
      return (
        
      {results.map(result => (
    • {result.name}
    • ))}
    ); } function SearchPage() { const [query, setQuery] = useState(''); const [isPending, startTransition] = useTransition(); const handleChange = (e) => { const value = e.target.value; // 紧急更新:立即更新输入框 setQuery(value); // 非紧急更新:标记搜索结果更新可以中断 startTransition(() => { setQuery(value); }); }; return (
    {/* 显示加载状态 */} {isPending &&
    加载中...
    } 搜索中...
    }> ); } // 注意:use 钩子目前还是实验性功能

    2. 自动批处理(Automatic Batching)

    // React 17 及之前:在事件处理程序外部的更新不会批处理
    setTimeout(() => {
      setCount(c => c + 1);
      setFlag(f => !f);
      // React 17 会渲染两次
    }, 1000);
    // React 18:所有更新都会自动批处理
    setTimeout(() => {
      setCount(c => c + 1);
      setFlag(f => !f);
      // React 18 只会渲染一次
    }, 1000);
    // 如果需要同步更新,可以使用 flushSync
    import { flushSync } from 'react-dom';
    function handleClick() {
      flushSync(() => {
        setCount(c => c + 1);
      });
      // DOM 已更新
      flushSync(() => {
        setFlag(f => !f);
      });
      // DOM 再次更新
    }

    总结

    React 作为一个强大而灵活的库,已经成为了现代 Web 开发的标准工具。通过本文的全面介绍,我们从基础概念到高级应用,从最佳实践到最新特性,系统地探索了 React 的方方面面。

    posted @ 2025-09-30 22:04  yxysuanfa  阅读(39)  评论(0)    收藏  举报