当前位置: 首页 > news >正文

React自学 基础一

React基础

React 是一个由 Facebook(现 Meta)开发并维护的、开源JavaScript 库,主要用于 构建用户界面(UI),尤其是单页面应用程序中的动态、交互式界面。

image-20250612192645692

简单示例:

import React, { useState } from 'react';function Counter() {const [count, setCount] = useState(0); // 使用 React Hooks 管理状态return (<div><p>You clicked {count} times</p><button onClick={() => setCount(count + 1)}>Click me</button></div>);
}

一、创建React工程

创建 React 项目主要有三种主流方式,根据你的需求(如开发效率、性能要求、是否需要服务端渲染等),可灵活选择以下任一方法:


🚀 一、使用 Vite(推荐:速度快、现代化)

Vite 是当前最受欢迎的 React 项目初始化工具,启动速度和热更新远超传统工具,适合绝大多数新项目。
操作步骤:

  1. 确保已安装 Node.js(建议 v16+)。

  2. 在终端执行以下命令:

    npm create vite@latest my-vite-app -- --template react
    
  3. 进入项目目录并安装依赖:

    cd my-vite-app
    npm install
    
  4. 启动开发服务器:

    npm run dev
    
    • 访问 http://localhost:5173 查看项目。
  5. 在Chrome浏览器中添加组件

    React 因其高效、灵活和强大的社区支持,成为现代前端开发的主流选择之一。

    在Chrome浏览器中添加组件

    image-20250628204026748

    image-20250628204129958


⚙️ 二、使用 Next.js(适合服务端渲染/静态站点)

若项目需服务端渲染(SSR)、静态生成(SSG)或强 SEO 支持(如博客、电商),Next.js 是最佳选择。
操作步骤:

  1. 创建项目:
    npx create-next-app@latest my-next-app
    
  2. 进入目录并启动:
    cd my-next-app
    npm run dev
    
    • 访问 http://localhost:3000

🧩 三、使用 create-react-app(传统方式,已逐渐淘汰)

虽然官方仍在维护,但启动慢、配置隐藏,仅适合学习或兼容旧项目。
操作步骤:

  1. 全局安装(可选):
    npm install -g create-react-app
    
  2. 创建项目:
    npx create-react-app my-app
    
  3. 启动项目:
    cd my-app
    npm start
    
    • 访问 http://localhost:3000

📊 三种方式对比与适用场景

工具优势适用场景启动命令
Vite⚡ 超快启动、轻量、配置灵活新项目、开发效率优先npm run dev
Next.js🌐 服务端渲染、SEO 友好、全栈能力博客、电商、需 SEO 的应用npm run dev
CRA🧠 零配置、官方维护(但慢)学习 React 基础npm start

常见问题解答(FAQ)

  • Q1:是否需要全局安装工具?
    不需要!现代工具(如 Vite、Next.js)通过 npx 直接运行最新版本,避免全局依赖冲突。
  • Q2:项目名称能否用大写字母?
    不能!所有工具均要求项目名全小写(如 my-app)。
  • Q3:如何修改默认端口?
    package.json 的启动命令后添加 --port=新端口号,例如:
    npm run dev -- --port=4000
    

💎 总结建议

  • 新手/一般项目 → 选 Vite,体验流畅开发;
  • 内容型网站/SEO 关键 → 选 Next.js,直接支持服务端渲染;
  • 学习 React 基础 → 可尝试 create-react-app,但注意其性能局限。

提示:以上命令均需在终端(如 VS Code 终端、命令行)执行。遇到依赖问题可尝试 npm install --force 强制重装。

image-20250612193145686

image-20250612193431658

image-20250630173947566

二、JSX

2.1 关于 JSX

JSX(JavaScript XML) 是一种 JavaScript 的语法扩展(解析工具进行特定解析),由 Facebook 团队为 React 框架设计。它的核心作用是将 HTML 结构直接嵌入 JavaScript 代码中,实现声明式的 UI 构建。

核心特点:
  1. 类 HTML 语法
    允许在 JavaScript 中编写类似 HTML 的标签(例如 <div>Hello</div>)。

  2. JavaScript 表达式嵌入
    { } 包裹动态内容(如变量、函数调用):

    const name = "Alice";
    const element = <h1>Hello, {name}</h1>; // 动态渲染
    
  3. 编译为 JavaScript
    JSX 本身不能被浏览器直接执行,需要通过工具(如 Babel)编译为标准 JavaScript:

    // 编译前 (JSX)
    <button className="btn">Click</button>// 编译后 (JavaScript)
    React.createElement("button", { className: "btn" }, "Click");
    
  4. 与 React 深度集成
    主要用于构建 React 组件的 UI 结构,但也可用于其他库(如 Vue 的 JSX 支持)。


2.2 关于 Babel (https://babeljs.io/)

Babel 是一个 JavaScript 编译器,它的核心功能是将新版本的 JavaScript 代码(或 JSX 等扩展语法)转换为向后兼容的旧版本 JavaScript,确保代码能在所有浏览器中运行。

关键作用:
  1. 编译 JSX
    将 JSX 语法转换为浏览器可理解的 React.createElement() 调用(如上例所示)。
  2. 转译现代 JavaScript
    将 ES6+ 代码(如箭头函数、async/await、类)转换为 ES5 等旧标准。
    // 编译前 (ES6)
    const list = items.map(item => <li key={item.id}>{item.name}</li>);// 编译后 (ES5)
    var list = items.map(function(item) {return React.createElement("li", { key: item.id }, item.name);
    });
    
  3. 插件化架构
    通过插件支持实验性语法(如装饰器)、类型检查(TypeScript)、代码优化等。

2.3 JSX 与 Babel 的关系

  1. 依赖 Babel 处理
    JSX 必须通过 Babel(或类似工具)编译为纯 JavaScript 才能运行。
  2. 常用预设
    在 React 项目中,通常使用 Babel 预设插件 @babel/preset-react 来编译 JSX。
  3. 工作流程示例
    JSX 代码
    Babel 编译
    标准 JavaScript
    浏览器执行

2.4 如何使用?

  1. 安装 Babel
    npm install @babel/core @babel/preset-react
    
  2. 配置 Babel(创建 .babelrc 文件):
    {"presets": ["@babel/preset-react"]
    }
    
  3. 与构建工具集成
    配合 Webpack/Rollup 等工具自动完成编译(例如使用 babel-loader)。

总结

  • JSX 是描述 UI 的语法糖,需编译为 JavaScript。
  • Babel 是编译工具链的核心,处理 JSX 和现代 JavaScript 的兼容性问题。
    官网 babeljs.io 提供了实时编译演示、插件文档和配置指南。

二(支线)、JSX 中使用 JavaScript 表达式

在 JSX 中,你可以使用大括号 {} 来嵌入 JavaScript 表达式。这允许你在 JSX 中动态地插入值、执行计算和渲染逻辑。

2.1 基本用法

const name = 'John Doe';
const element = <h1>Hello, {name}</h1>;

image-20250701154930359

2.2 表达式类型

  1. 变量引用

    const user = { firstName: 'Jane', lastName: 'Doe' };
    const element = <p>{user.firstName} {user.lastName}</p>;
    
  2. 函数调用

   function formatName(user) {return `${user.firstName} ${user.lastName}`;}const element = <h2>{formatName(user)}</h2>;
  1. 算术运算
   const total = 10;const count = 3;const element = <p>Remaining: {total - count}</p>;
  1. 三元表达式

    const isLoggedIn = true;
    const element = (<div>{isLoggedIn ? 'Welcome back!' : 'Please sign in'}</div>
    );
  2. 数组方法(列表渲染)

 const numbers = [1, 2, 3, 4, 5];const listItems = numbers.map((number) => <li key={number}>{number}</li>);

2.3 JSX 中的列表渲染示例

列表渲染是 React 中常见的操作,通常使用 map() 方法来遍历数组并生成一组 JSX 元素。下面提供多个不同场景的列表渲染示例:

2.3.1 基础列表渲染
const fruits = ['Apple', 'Banana', 'Orange'];function FruitList() {return (<ul>{fruits.map((fruit, index) => (<li key={index}>{fruit}</li>))}</ul>);
}
2.3.2 对象数组渲染
const users = [{ id: 1, name: 'Alice', age: 25 },{ id: 2, name: 'Bob', age: 30 },{ id: 3, name: 'Charlie', age: 35 }
];function UserTable() {return (<table><thead><tr><th>Name</th><th>Age</th></tr></thead><tbody>{users.map(user => (<tr key={user.id}><td>{user.name}</td><td>{user.age}</td></tr>))}</tbody></table>);
}
2.3.3 带条件的列表渲染

在 JSX 中,我们经常需要根据条件来决定是否渲染某些内容。JavaScript 的逻辑与 (&&) 运算符和三元运算符 (?:) 是两种常用的条件渲染方式。

1. 逻辑与 (&&) 运算符
{condition && <Component />}

condition 为真时,渲染 <Component />;否则不渲染任何内容。

示例
function Greeting({ isLoggedIn }) {return (<div>{isLoggedIn && <h1>Welcome back!</h1>}</div>);
}// 使用
<Greeting isLoggedIn={true} />  // 显示 "Welcome back!"
<Greeting isLoggedIn={false} /> // 不显示任何内容
特点
  • 简洁,适合简单的条件渲染
  • 当条件为 false 时,React 会跳过渲染(不会渲染 nullfalse
  • 注意:如果 condition0 这样的 falsy 值,会渲染 0 而不是跳过
2. 三元运算符 (?:)
{condition ? <ComponentA /> : <ComponentB />}

condition 为真时,渲染 <ComponentA />;否则渲染 <ComponentB />

示例
function Greeting({ isLoggedIn }) {return (<div>{isLoggedIn ? (<h1>Welcome back!</h1>) : (<h1>Please sign in.</h1>)}</div>);
}// 使用
<Greeting isLoggedIn={true} />  // 显示 "Welcome back!"
<Greeting isLoggedIn={false} /> // 显示 "Please sign in."
特点
  • 适合需要两种不同渲染结果的场景
  • 更明确地表达两种可能性
  • 可以嵌套使用(但不推荐过于复杂的嵌套)
3. 在 JSX 外部使用 if 语句
提前决定要渲染的内容
function Greeting({ isLoggedIn }) {let content;if (isLoggedIn) {content = <h1>Welcome back!</h1>;} else {content = <h1>Please sign in.</h1>;}return <div>{content}</div>;
}
function renderContent(isLoggedIn) {if (isLoggedIn) {return <h1>Welcome back!</h1>;}return <h1>Please sign in.</h1>;
}function Greeting({ isLoggedIn }) {return <div>{renderContent(isLoggedIn)}</div>;
}
4. 立即执行函数来包含 if 逻辑
function Greeting({ isLoggedIn }) {return (<div>{(() => {if (isLoggedIn) {return <h1>Welcome back!</h1>;} else {return <h1>Please sign in.</h1>;}})()}</div>);
}
5.使用 switch 语句
function StatusIndicator({ status }) {let indicator;switch (status) {case 'loading':indicator = <Spinner />;break;case 'success':indicator = <Checkmark />;break;case 'error':indicator = <ErrorIcon />;break;default:indicator = null;}return <div>{indicator}</div>;
}
6.比较
方法适用场景优点缺点
外部 if复杂条件逻辑清晰易读需要额外变量
IIFE简单内联条件保持内联语法稍复杂
提取函数可复用的条件渲染可复用,易于测试需要跳转查看逻辑
switch多个互斥条件结构清晰代码量较多
&& 运算符单一条件,渲染或不渲染简洁只能处理单一条件
三元运算符二选一渲染表达式形式,内联嵌套时难以阅读
最佳实践建议
处理 false 值的注意事项
// 当 count 为 0 时,&& 会渲染 0
{count && <Message count={count} />}// 修复方法:明确布尔值转换
{count > 0 && <Message count={count} />}
{!!count && <Message count={count} />}
  1. 简单条件:使用 && 更简洁
  2. 二选一渲染:使用三元运算符
  3. 避免复杂嵌套:如果条件太复杂,考虑提取为函数或组件
  4. 保持可读性:复杂的条件逻辑可以拆分成多个变量

选择哪种方式主要取决于具体场景和个人/团队的编码风格偏好,重要的是保持代码的一致性和可读性。

const products = [{ id: 1, name: 'Laptop', inStock: true },{ id: 2, name: 'Phone', inStock: false },{ id: 3, name: 'Tablet', inStock: true }
];function ProductList() {return (<ul>{products.map(product => (product.inStock && (<li key={product.id}>{product.name} - {product.inStock ? 'In Stock' : 'Out of Stock'}</li>)))}</ul>);
}
2.3.4 嵌套列表渲染
const departments = [{id: 1,name: 'Development',employees: ['John', 'Jane', 'Mike']},{id: 2,name: 'Design',employees: ['Sarah', 'Tom']}
];function DepartmentList() {return (<div>{departments.map(dept => (<div key={dept.id}><h3>{dept.name}</h3><ul>{dept.employees.map((employee, index) => (<li key={index}>{employee}</li>))}</ul></div>))}</div>);
}
2.3.5 使用组件渲染列表项
function TodoItem({ todo }) {return (<li><input type="checkbox" checked={todo.completed} /><span>{todo.text}</span></li>);
}function TodoList() {const todos = [{ id: 1, text: 'Learn React', completed: true },{ id: 2, text: 'Build a project', completed: false },{ id: 3, text: 'Deploy to production', completed: false }];return (<ul>{todos.map(todo => (<TodoItem key={todo.id} todo={todo} />))}</ul>);
}
2.3.6 重要注意事项
  1. key 属性:列表中的每个元素都应该有一个唯一的 key 属性,通常使用数据中的 ID,

    // 好
    {items.map(item => <li key={item.id}>{item.name}</li>)}// 如果没有 ID,可以使用索引(但不推荐用于动态列表)
    {items.map((item, index) => <li key={index}>{item.name}</li>)}
    
  2. 避免在渲染时修改数据:不要在 map 内部修改原始数组

  3. 性能优化:对于大型列表,考虑使用虚拟滚动技术(如 react-window 库)

2.4 注意事项

  • JSX 中的表达式必须是返回值的表达式,不能使用语句(如 if 语句)
  • 对于条件渲染,可以使用三元运算符或逻辑与 (&&) 运算符
  • 对象不能直接作为子元素渲染,需要转换为字符串或提取特定属性
// 错误示例
const user = { name: 'John' };
const element = <div>{user}</div>; // 错误// 正确示例
const element = <div>{user.name}</div>; // 正确
const element = <div>{JSON.stringify(user)}</div>; // 正确

JSX 中的 JavaScript 表达式使得动态 UI 的创建变得简单而强大。

image-20250701154101729

三、事件绑定+组件

3.1 React事件绑定

在 JSX 中绑定 React 事件与在 HTML 中绑定 DOM 事件类似,但有一些关键区别。以下是 React 事件绑定的主要特点和使用方法:

3.1.1 基本语法
<button onClick={handleClick}>点击我
</button>
(1)与 HTML 事件的区别
  1. 命名采用驼峰式onclickonClickonchangeonChange
  2. 传入函数而不是字符串onclick="handleClick()"onClick={handleClick}
  3. 默认行为阻止方式不同:不能通过返回 false 来阻止默认行为
(2)常见事件类型
  • onClick - 点击事件
  • onChange - 表单元素变化
  • onSubmit - 表单提交
  • onMouseEnter - 鼠标进入
  • onMouseLeave - 鼠标离开
  • onKeyDown - 键盘按下
  • onFocus - 获取焦点
  • onBlur - 失去焦点
3.1.2【1】事件处理函数
function handleClick(event) {// event 是合成事件(SyntheticEvent)console.log('按钮被点击了', event);
}function App() {return <button onClick={handleClick}>点击</button>;
}

3.1.2 【2】 传递参数
(1)如果需要传递额外参数给事件处理函数
function handleClick(id, event) {console.log('ID:', id, '事件:', event);
}function App() {return (<button onClick={(e) => handleClick(123, e)}>带参数点击</button>);
}

image-20250701175635340

🔍 特点分析:
  • 事件对象正确传递onClick={(e) => handleClick(123, e)} 中的 e 是 React 事件对象,被显式传递给了 handleClick 函数。
  • 函数签名匹配handleClick(id, event) 的两个参数(idevent)都得到了正确的值。
  • 用途场景:当需要访问事件对象(如阻止默认行为、获取事件目标等)时,这种方式是推荐的。
(2)箭头函数的

不能直接写函数调用,这事件绑定需要一个函数引用

function handleClick(event) {console.log('事件:', event);
}const App = () => {return (<button onClick={() => handleClick(123)}>带参数点击</button>);
};

image-20250701175624204

🔍 问题分析:
  • 事件对象未传递onClick={() => handleClick(123)} 中的 handleClick 仅接收 123 作为参数,事件对象(event)没有被传入
  • 函数签名不匹配handleClick(event) 期望的是一个 event 参数,但实际传入的是 123,因此 event 参数会是 undefined
  • 潜在错误:如果 handleClick 中依赖 event 的值(如 event.target.valueevent.preventDefault() 等),会导致运行时错误或行为异常。
3.1.3 类组件中的绑定

在类组件中,通常需要在构造函数中绑定 this 或使用箭头函数:

class MyComponent extends React.Component {constructor(props) {super(props);this.handleClick = this.handleClick.bind(this);}handleClick() {console.log('this:', this);}// 或者使用箭头函数自动绑定 thishandleClick = () => {console.log('this:', this);}render() {return <button onClick={this.handleClick}>点击</button>;}
}
3.1.4阻止默认行为和事件冒泡
function handleClick(event) {event.preventDefault(); // 阻止默认行为event.stopPropagation(); // 阻止事件冒泡console.log('事件处理');
}
3.1.5 合成事件(SyntheticEvent)

React 的事件是合成事件,是对原生事件的跨浏览器包装,具有与原生事件相同的接口,包括:

  • event.preventDefault()
  • event.stopPropagation()
  • event.target
  • event.currentTarget
3.1.6 注意事项
  1. 事件处理函数中的 this 默认不是组件实例,需要手动绑定
  2. 避免在 render 方法中创建新函数,可能导致不必要的重新渲染
  3. React 17+ 中事件委托不再附加到 document,而是附加到 React 渲染的根 DOM 容器

正确的事件绑定方式可以帮助你编写更高效、更易维护的 React 组件。

3.2 React组件

3.2.1 基础使用

React 组件是构建用户界面的独立、可复用的代码单元,将 UI 拆分为独立模块。每个组件管理自身的状态和逻辑,通过组合形成复杂界面。

image-20250703132838717

/*原生写法*/
function Button (){return <button>Button</button>
}/*或者使用箭头函数的写法*/
const Button = () =>{return <button>Button</button>
}

使用上

/*自闭和*/
<Button/>
/*成对标签*/
<Button/><Button/>
3.2.2 基础样式控制

在 React 中,控制组件样式有多种基础方式,每种方式各有适用场景。以下是主要方法及代码示例:

1. 内联样式 (Inline Styles)

直接在 JSX 元素中使用 style 属性,传入样式对象(属性名需驼峰命名

function Button() {return (<button style={{padding: "10px 20px",backgroundColor: "blue",color: "white",borderRadius: "4px",cursor: "pointer"}}>点击我</button>);
}

特点

  • ✅ 简单直接,适合动态样式
  • ❌ 无法使用伪类(:hover)和媒体查询
  • ❌ 性能不如 CSS 类(大量使用可能影响渲染)

2. 外部 CSS 文件

传统 CSS 引入方式(最常用)

/* Button.css */
.my-button {padding: 10px 20px;background-color: blue;color: white;border-radius: 4px;cursor: pointer;
}.my-button:hover {background-color: darkblue; /* 支持伪类 */
}

组件中引入:

import "./Button.css";function Button() {return <button className="my-button">点击我</button>;
}

特点

  • ✅ 支持所有 CSS 特性
  • ✅ 浏览器缓存优化
  • ❌ 全局作用域(需注意类名冲突)

3. CSS Modules(推荐)

自动局部作用域(文件命名:[name].module.css

/* Button.module.css */
.button {padding: 10px 20px;background: blue;
}

组件中使用:

import styles from "./Button.module.css";function Button() {return <button className={styles.button}>点击我</button>;
}

编译后类名会变成唯一值(如 Button_button__1H2k5

特点

  • ✅ 避免类名冲突
  • ✅ 支持所有 CSS 特性
  • ✅ 与普通 CSS 写法一致

4. CSS-in-JS 库 (如 styled-components)

通过 JavaScript 编写样式(需安装库)

npm install styled-components
import styled from "styled-components";// 创建带样式的组件
const StyledButton = styled.button`padding: 10px 20px;background: ${props => props.primary ? "blue" : "gray"};color: white;border-radius: 4px;&:hover {background: darkblue; /* 支持伪类 */}
`;function App() {return (<><StyledButton>普通按钮</StyledButton><StyledButton primary>主要按钮</StyledButton></>);
}

特点

  • ✅ 动态样式支持最佳
  • ✅ 自动处理作用域
  • ❌ 增加包体积
  • ❌ 学习曲线较陡

5. 实用类库 (Tailwind CSS)

原子化 CSS 方案(需配置)

function Button() {return (<button className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600">点击我</button>);
}

特点

  • ✅ 快速原型开发
  • ✅ 响应式设计便捷
  • ❌ 需学习类名系统
  • ❌ HTML 可能臃肿

选择建议:
场景推荐方式
简单原型/少量动态样式内联样式
传统项目/团队熟悉 CSS外部 CSS + BEM
组件化/避免类名冲突CSS Modules
复杂动态样式/主题系统CSS-in-JS
快速开发/统一设计系统Tailwind CSS

最佳实践提示

  1. 大型项目推荐 CSS ModulesCSS-in-JS
  2. 避免过度使用内联样式(性能考虑)
  3. 动态样式可结合:className 条件拼接 或 CSS 变量
  4. 使用 :where() 降低 CSS 特异性(如 :where(.card) .title

四、useState

useState 是 React 中用于声明组件状态的一个 Hook,它让函数组件能够拥有自己的内部状态。(向组件添加一个状态变量,一旦变化UI也随之变化**(数据驱动视图**))

通过 useState,你可以在组件内部保存数据并在数据发生变化时重新渲染组件。

image-20250703133721750

4.1 useState 基础结构

const [state, setState] = useState(initialValue);
  • state:当前状态值(只读)
  • setState:更新状态的函数
  • initialValue:状态的初始值(可以是任何类型)
React原则
🔒 状态是只读的
📖 状态读取
🚫 不可直接修改
🔄 状态更新
🆕 必须创建新值替换
✨ 状态替换
📥 状态初始化

4.2 状态不可变性原则详解

4.2.1 为什么状态必须不可变?
  1. 变更检测:React 通过引用比较检测状态变化
  2. 性能优化:避免不必要的重新渲染
  3. 可预测性:状态变更路径清晰可追踪
  4. 时间旅行调试:支持状态历史记录和回滚
4.2.2 错误 vs 正确更新方式对比

必须创建状态的新副本进行替换,而不是直接修改现有状态。

状态类型错误方式(直接修改)正确方式(创建新值)
对象user.age = 31;
setUser(user);
setUser({...user, age: 31});
数组items.push('new');
setItems(items);
setItems([...items, 'new']);
嵌套对象user.address.city = 'Paris';setUser({...user, address: {...user.address, city: 'Paris'}});

image-20250703145808001

4.3 待处理:状态管理实战模式

1. 表单状态处理
function UserForm() {const [user, setUser] = useState({name: '',email: '',preferences: { theme: 'light', notifications: true }});const handleChange = (field, value) => {setUser(prev => ({...prev,[field]: value}));};const toggleTheme = () => {setUser(prev => ({...prev,preferences: {...prev.preferences,theme: prev.preferences.theme === 'light' ? 'dark' : 'light'}}));};return (<form><input value={user.name} onChange={e => handleChange('name', e.target.value)} /><input value={user.email} onChange={e => handleChange('email', e.target.value)} /><button type="button" onClick={toggleTheme}>切换主题(当前:{user.preferences.theme}</button></form>);
}

image-20250703144751042

2. 列表状态管理
function TodoList() {const [todos, setTodos] = useState([{ id: 1, text: '学习React', completed: false }]);// 添加新任务(创建新数组)const addTodo = text => {setTodos(prev => [...prev,{ id: Date.now(), text, completed: false }]);};// 切换任务状态(创建新对象)const toggleTodo = id => {setTodos(prev => prev.map(todo => todo.id === id ? { ...todo, completed: !todo.completed } : todo));};// 删除任务(创建过滤后的新数组)const deleteTodo = id => {setTodos(prev => prev.filter(todo => todo.id !== id));};return (<div><ul>{todos.map(todo => (<li key={todo.id}><input type="checkbox"checked={todo.completed}onChange={() => toggleTodo(todo.id)}/><span style={{ textDecoration: todo.completed ? 'line-through' : 'none' }}>{todo.text}</span><button onClick={() => deleteTodo(todo.id)}>删除</button></li>))}</ul></div>);
}

4.4 待处理:高级技巧与优化策略

1. 函数式更新
// 当新状态依赖旧状态时使用
setCount(prevCount => prevCount + 1);// 批量更新示例
const incrementTwice = () => {setCount(prev => prev + 1); // 使用前值计算setCount(prev => prev + 1); // 确保两次更新都生效
};
2. 惰性初始化
// 复杂初始状态的计算只执行一次
const [data, setData] = useState(() => {const expensiveValue = calculateExpensiveValue();return expensiveValue;
});
3. 状态结构优化
复杂状态
拆分为多个useState
使用useReducer
使用Immer库
提高可读性
集中状态逻辑
简化不可变更新
4. 使用 Immer 简化不可变更新
import produce from 'immer';const [user, setUser] = useState({name: 'Alice',profile: {level: 5,achievements: ['新手', '探索者']}
});// 使用 Immer 进行"可变式"更新(底层仍不可变)
const addAchievement = title => {setUser(produce(draft => {draft.profile.achievements.push(title);}));
};const updateLevel = () => {setUser(produce(draft => {draft.profile.level += 1;}));
};
http://www.dtcms.com/a/265704.html

相关文章:

  • 基于大语言模型进行Prompt优化
  • 深入解析 AAC AudioSpecificConfig 在 RTSP/RTMP 播放器中的核心作用
  • PDF的图片文字识别工具
  • Spring AI ETL Pipeline使用指南
  • Java中的volatile到底是什么来路
  • OpenCV CUDA模块设备层-----在 GPU上高效地执行两个uint类型值的最小值比较函数vmin2()
  • 《人生顶层设计》读书笔记6
  • 开源无广告面板mdserver-web:替代宝塔实现服务器轻松管理
  • 地下管线安全的智能监测先锋:智能标志桩图像监测装置解析​
  • 矩阵批量剪辑源码搭建定制化开发:支持OEM
  • 爬虫技术-获取浏览器身份认证信息(如 Cookie、Token、Session 等)
  • Python 中如何使用 Conda 管理版本和创建 Django 项目
  • 【Docker】如何设置 `wiredTigerCacheSizeGB` 和 `resources.limits.memory`
  • BenchmarkSQL 测试 PostgreSQL 时遇到 numeric field overflow 报错的原因与解决方案
  • 请求未达服务端?iOS端HTTPS链路异常的多工具抓包排查记录
  • 区块链真的会是未来吗?
  • TCP粘包、拆包、解决
  • 什么是协同归因和贡献归因
  • WhoDB:一款基于Web的免费AI数据库管理工具
  • 刷卡登入数据获取
  • 【ArcGISPro】基于Pro的Python环境进行Django简单开发Web
  • 两个PHY芯片之间,是如何连接进行通信的?
  • 并行科技MaaS平台支持文心4.5系列开源模型调用
  • MySQL主从延迟深度解析:现象、原因与实战解决方案
  • KMP(Kotlin Multiplatform)改造(Android/iOS)老项目
  • 舵轮时钟-STM32-28路PWM--ESP8266-NTP时间
  • Babylon.js 材质克隆与纹理共享:你可能遇到的问题及解决方案
  • 从UI设计到数字孪生实战演练:构建智慧城市的智慧停车系统
  • 大势智慧亮相第十八届中国智慧城市大会
  • 暑期出游,解锁“智慧”新玩法!