实用指南:React基础到进阶

news/2025/9/30 22:11:01/文章来源:https://www.cnblogs.com/yxysuanfa/p/19121841

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 creatorsconst 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 的方方面面。

    本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/923299.shtml

    如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

    相关文章

    如何做营销型手机网站优化做网站招聘的职业顾问

    关于DRL的WTI模块&#xff1a; Weighted Token-wise Interaction&#xff1a; 直觉上&#xff0c;并非所有的单词和视频帧都同等重要。我们提供一种自适应方法&#xff0c;来调整每个标记的权重大小&#xff1a; 注&#xff1a;其中两个f函数都是MLP和softmax构成。 WTI的算…

    九龙坡网站建设哪家好宝塔 wordpress 教程

    在使用M1 在安装cocopods 前时&#xff0c;安装 rvm install 3.0.0遇到 rvm install 3.0.0 Error running __rvm_make -j8 备注: 该图片是借用其他博客图片&#xff0c;因为我的环境解决完没有保留之前错误信息。 解决方法如下&#xff1a; 1. brew uninstall --ignore-depe…

    网站上内容列表怎么做的网站开发为什么要用框架

    概述分享下最近做的一个mysql大表归档方案&#xff0c;仅供参考。整体思路一、明确哪些大表需做归档1、数据库表概要信息统计SELECTt1.table_schema,t1.table_name,ENGINE,table_rows,CAST( data_length / 1024.0 / 1024.0 AS DECIMAL ( 10, 2 ) ) data_size(M),CAST( index_le…

    bat批处理设置临时PATH路径不能访问

    前言全局说明一、说明 1.1 环境: Windows 7 旗舰版二、通常设置路径方法 set adb_PATH=d:\adb_dir set PATH=%PATH%;%adb_PATH%直接在命令行里这么写没问题 在bat脚本中,会提示找不到路径下命令三、解决方法 使用环境…

    电子商务网站开发工具网站营销外包公司简介

    来源&#xff1a;博客丨政策管理作者&#xff1a;贺飞&#xff08;北京大学&#xff09;摘要&#xff1a;量子计算&#xff1a;前途光明 道路曲折量子计算&#xff1a;前途光明 道路曲折&#xff08;一&#xff09;本周&#xff0c;美国国家科学院、工程院和医学院的一个由13…

    2025-2026-1 20231301 《信息安全设计》第九周学习总结

    View Post2025-2026-1 20231301 《信息安全设计》第九周学习总结2025-2026-1 20231301 《信息安全设计》第九周学习总结 目录作业信息学习内容总结1. 进程的本质2. 系统调用层次结构3. 进程创建与执行完整流程exec() 函…

    手机网站锁定竖屏看代码建设部网站水利设计资质

    合作官宣 TopOn 正式成为亚太地区首家支持自动创建Admob bidding广告源的聚合平台。目前&#xff0c;在TopOn后台添加Admob广告平台&#xff0c;您只需要重新授权Google账号&#xff0c;即可开通自动创建功能。此前&#xff0c;TopOn 已在24年2月6日官方聚合支持Google biddin…

    10. Spring AI + RAG - Rainbow

    10. Spring AI + RAG @目录10. Spring AI + RAGRAG概念向量:文本向量化向量数据库匹配检索SearchRequest接入ChatClientRetrievalAugmentationAdvisor最后: RAG 检索增强生成(Retrieval-augmented Generation) 对…

    《AI智能体实战研发教程(从0到企业级项目落地)》全网上线|CSDN B站同步首发

    《AI智能体实战研发教程(从0到企业级项目落地)》全网上线|CSDN & B站同步首发pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; f…

    网站更改备案信息在哪好网站开发

    Hive常用函数_20个字符串处理 以下是Hive中常用的字符串处理函数&#xff0c;可用于执行各种字符串处理转换操作。 1. CONCAT()&#xff1a;将多个字符串连接在一起。 SELECT CONCAT(Hello, World); -- Output: HelloWorld2. SUBSTR()&#xff1a;从字符串中提取子字符串&…

    9. Spring AI 当中对应 MCP 的操作 - Rainbow

    9. Spring AI 当中对应 MCP 的操作 @目录9. Spring AI 当中对应 MCP 的操作MCP问题:使用MCP STDIO 输出配置实操MCP Server现成共用MCP ServerMCP Client通过工具通过 Spring AI 接入 第三方的 MCP Server使用 Spring…

    深入解析:JVM 内存结构

    pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

    gudao网站建设闸北东莞网站建设

    7-13 p070找出全部子串位置 分数 5 作者 吴敏华 单位 首都师范大学 输入两个串s1,s2&#xff0c;找出s2在s1中所有出现的位置。 前后两个子串的出现不能重叠。例如’aa’在 aaaa 里出现的位置只有0,2 输入格式: 第一行是整数n 接下来有n行&#xff0c;每行两个不带空格的字符…

    深圳微信网站建设报价九游手游平台app

    一、利用webapps文件夹自动部署这是最简单的方式&#xff0c;只要将网站直接拷贝到&#xff1a;tomcat根目录下的webapps文件夹里举例&#xff1a;helloworld文件夹下创建里index.html文件&#xff0c;然后把helloworld文件夹移动到tomcat根目录下webapps文件夹里&#xff0c;重…

    9/30

    今天上午上了一节工程实训的课,其中小车红外线测距系统用到了C语言,第一次真正的用到了所学知识,感觉不错,四节课很快过去了,明天就是国庆,开心

    rhel8无法输入中文问题(红帽8安装中文输入法)

    问题:明明在设置里添加了汉语拼音输入法缺无法输入中文解决方法: 通过yum安装中文输入法 [root@server01 ~]# dnf install ibus-libpinyin -y到设置里添加新安装的输入法发现还没有新安装的输入法,这时需要重启系统…

    威佐夫博弈(Wythoff‘s Game)

    威佐夫博弈(Wythoff‘s Game) 1. Beatty 定理 设 无理数 \(r\) 对应的 Beatty 数列 \(B_r\) 为 \((B_r)_i=\lfloor i\times r\rfloor\)。 定理:若无理数 \(r,s\) 满足 \(\frac 1 r+\frac 1 s=1\),则 \(B_r,B_s\) 为…

    外贸网站收到询盘淘客网站建设视频

    目录 一、modbus简介 二、功能码01、02 三、modbus解析 四、功能码03、04 五、功能码05 六、功能码06 七、功能码16 一、modbus简介 我们在网上查阅modbus的资料发现很多很杂&#xff0c;modbus-RTU ASCII TCP等等&#xff0c;还有跟PLC结合的&#xff0c;地址还分1开…

    PWN手成长之路-05-ROP

    与远程环境进行交互,可以进行输入,但是输入之后无任何回显。file 查看文件。64位 ELF 。checksec 查看文件安全属性。IDA 打开文件。查看 main 函数的反编译代码。查看 buf 这个字符数组(栈上的缓冲区),本身 buf …