Jacky's blog
首页
  • 学习笔记

    • web
    • android
    • iOS
    • vue
  • 分类
  • 标签
  • 归档
收藏
  • tool
  • algo
  • python
  • java
  • server
  • growth
  • frida
  • blog
  • SP
  • more
GitHub (opens new window)

Jack Yang

编程; 随笔
首页
  • 学习笔记

    • web
    • android
    • iOS
    • vue
  • 分类
  • 标签
  • 归档
收藏
  • tool
  • algo
  • python
  • java
  • server
  • growth
  • frida
  • blog
  • SP
  • more
GitHub (opens new window)
  • web
  • web concept
  • javascript

  • css

  • vue

  • react

    • React 完整学习指南
      • 📚 你将学到什么
      • 🎯 学习路径建议
      • 📖 目录
      • 🔧 前置知识
        • JavaScript 基础
        • 前端基础
        • 推荐学习资源
      • 🚀 环境搭建
        • 1. 安装 Node.js
        • 2. 创建 React 项目
        • 3. 开发工具配置
        • VS Code 推荐插件
        • 项目结构
      • ⚛️ React 基础
        • 1. JSX 语法
        • 基本语法
        • 条件渲染
        • 列表渲染
        • 2. 组件基础
        • 函数组件
        • 类组件
        • Props 传递
        • 3. 事件处理
        • 4. 基础项目实践
        • 计数器组件
        • 待办事项应用
      • 🎣 Hooks 系统
        • 1. 基础 Hooks
        • useState - 状态管理
        • useEffect - 副作用处理
        • useContext - 上下文使用
        • 2. 高级 Hooks
        • useCallback - 函数缓存
        • useMemo - 值缓存
        • useRef - 引用管理
        • useReducer - 复杂状态管理
        • 3. 自定义 Hooks
        • 常用自定义 Hooks
      • 🔄 状态管理
        • 1. Redux Toolkit
        • 安装和配置
        • Store 配置
        • Slice 创建
        • 异步操作
        • 在组件中使用
        • 2. Zustand
        • 安装
        • 创建 Store
        • 在组件中使用
        • 3. Context + useReducer
      • ⚡ 性能优化
        • 1. React.memo
        • 2. useMemo 和 useCallback
        • 3. 代码分割和懒加载
      • 🚀 实战项目
        • 电商购物车应用
      • ❓ 常见问题
        • Q1: 什么时候使用 useCallback 和 useMemo?
        • Q2: 如何避免不必要的重新渲染?
        • Q3: 如何处理异步数据获取?
        • Q4: 如何调试 React 应用?
        • Q5: 如何优化大型列表的性能?
      • 📚 学习资源
        • 官方文档
        • 在线教程
        • 工具和库
        • 社区资源
        • 实践项目
      • 🎯 学习建议
        • 时间安排
        • 学习方法
        • 技能评估
      • 🎉 总结
        • 下一步学习建议
        • 记住这些要点
    • React Hooks 完整指南
    • REACT NATIVE
    • REACT 实用代码片段
    • REACT 高频问题
  • nextjs

  • module

  • web faq
  • web3

  • more

  • 《web》
  • react
Jacky
2023-11-10
目录

React 完整学习指南

# ⚛️ React 完整学习指南

适合人群:前端开发者、JavaScript开发者、移动端开发者
学习时间:3-6个月
前置知识:HTML、CSS、JavaScript基础、ES6+语法

React 是 Facebook 开发的用于构建用户界面的 JavaScript 库,是现代前端开发的核心技术之一。本指南将带你从零开始,系统性地学习 React 开发。

# 📚 你将学到什么

  1. React 基础 - 掌握组件、JSX、状态管理等核心概念
  2. Hooks 系统 - 学会使用现代 React 开发模式
  3. 状态管理 - 掌握 Redux、Zustand 等状态管理方案
  4. 性能优化 - 学会优化 React 应用性能
  5. 实战项目 - 完成完整的 React 应用开发

# 🎯 学习路径建议

graph TD A[JavaScript基础] --> B[React基础] B --> C[JSX语法] C --> D[组件开发] D --> E[Hooks系统] E --> F[状态管理] F --> G[路由管理] G --> H[性能优化] H --> I[实战项目]

# 📖 目录

  • 前置知识
  • 环境搭建
  • React 基础
  • Hooks 系统
  • 状态管理
  • 性能优化
  • 实战项目
  • 常见问题
  • 学习资源

# 🔧 前置知识

在开始学习 React 之前,你需要掌握以下基础知识:

# JavaScript 基础

  • ES6+ 语法(箭头函数、解构赋值、模板字符串等)
  • 数组方法(map、filter、reduce 等)
  • 异步编程(Promise、async/await)
  • 模块系统(import/export)

# 前端基础

  • HTML5 语义化标签
  • CSS3 布局(Flexbox、Grid)
  • 响应式设计
  • 浏览器开发者工具

# 推荐学习资源

  • MDN JavaScript 指南 (opens new window) - JavaScript基础语法
  • ES6 入门教程 (opens new window) - 现代JavaScript特性
  • CSS 布局指南 (opens new window) - CSS布局基础

完整学习资源:请参考文档末尾的"学习资源"章节。

# 🚀 环境搭建

# 1. 安装 Node.js

# 检查 Node.js 版本
node --version
npm --version

# 推荐使用 Node.js 18+ 版本
1
2
3
4
5

# 2. 创建 React 项目

# 使用 Create React App
npx create-react-app my-react-app
cd my-react-app
npm start

# 使用 Vite(推荐,更快)
npm create vite@latest my-react-app -- --template react
cd my-react-app
npm install
npm run dev
1
2
3
4
5
6
7
8
9
10

# 3. 开发工具配置

# VS Code 推荐插件

{
  "recommendations": [
    "ms-vscode.vscode-typescript-next",
    "bradlc.vscode-tailwindcss",
    "esbenp.prettier-vscode",
    "ms-vscode.vscode-eslint",
    "formulahendry.auto-rename-tag",
    "christian-kohler.path-intellisense"
  ]
}
1
2
3
4
5
6
7
8
9
10

# 项目结构

my-react-app/
├── public/
│   ├── index.html
│   └── favicon.ico
├── src/
│   ├── components/          # 组件目录
│   ├── pages/              # 页面目录
│   ├── hooks/              # 自定义 Hooks
│   ├── utils/              # 工具函数
│   ├── styles/             # 样式文件
│   ├── App.js              # 主应用组件
│   └── index.js            # 应用入口
├── package.json
└── README.md
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# ⚛️ React 基础

# 1. JSX 语法

JSX 是 JavaScript 的语法扩展,让你可以在 JavaScript 中编写类似 HTML 的代码。

# 基本语法

// 基本 JSX
const element = <h1>Hello, React!</h1>;

// 表达式
const name = "React";
const element = <h1>Hello, {name}!</h1>;

// 属性
const element = <div className="container" id="main">Content</div>;
1
2
3
4
5
6
7
8
9

# 条件渲染

function Greeting({ isLoggedIn, username }) {
  return (
    <div>
      {isLoggedIn ? (
        <h1>Welcome back, {username}!</h1>
      ) : (
        <h1>Please log in.</h1>
      )}
    </div>
  );
}

// 使用 && 操作符
function Mailbox({ unreadMessages }) {
  return (
    <div>
      <h1>Hello!</h1>
      {unreadMessages.length > 0 && (
        <h2>You have {unreadMessages.length} unread messages.</h2>
      )}
    </div>
  );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 列表渲染

function TodoList({ todos }) {
  return (
    <ul>
      {todos.map(todo => (
        <li key={todo.id}>
          {todo.text}
        </li>
      ))}
    </ul>
  );
}

// 复杂列表渲染
function ProductList({ products }) {
  return (
    <div className="product-grid">
      {products.map(product => (
        <div key={product.id} className="product-card">
          <img src={product.image} alt={product.name} />
          <h3>{product.name}</h3>
          <p>${product.price}</p>
          <button onClick={() => addToCart(product.id)}>
            Add to Cart
          </button>
        </div>
      ))}
    </div>
  );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

# 2. 组件基础

# 函数组件

// 简单函数组件
function Welcome({ name }) {
  return <h1>Hello, {name}!</h1>;
}

// 带状态的函数组件(使用 Hooks)
import { useState } from 'react';

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

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

函数组件的特点:

  • 简洁性:语法简洁,易于理解和编写
  • 性能优化:React 16.8+ 支持 Hooks,性能与类组件相当
  • 现代开发:React 官方推荐使用函数组件
  • 易于测试:纯函数特性,便于单元测试
  • 代码复用:通过自定义 Hooks 实现逻辑复用
  • TypeScript 友好:类型推断更准确,类型定义更简单

# 类组件

class Welcome extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
  }

  handleClick = () => {
    this.setState({ count: this.state.count + 1 });
  }

  render() {
    return (
      <div>
        <h1>Hello, {this.props.name}!</h1>
        <p>Count: {this.state.count}</p>
        <button onClick={this.handleClick}>Increment</button>
      </div>
    );
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

类组件的特点:

  • 生命周期:提供完整的生命周期方法(componentDidMount、componentDidUpdate 等)
  • 状态管理:通过 this.state 和 this.setState 管理状态
  • 错误边界:可以实现错误边界(Error Boundaries)
  • 历史兼容:React 早期版本的主要组件形式
  • 复杂逻辑:适合处理复杂的组件逻辑和状态管理
  • 学习成本:需要理解 this 绑定、生命周期等概念

注意:虽然类组件仍然被支持,但 React 官方推荐使用函数组件 + Hooks 的开发模式。

# Props 传递

// 父组件
function App() {
  const user = { name: "John", age: 30 };
  
  return (
    <div>
      <UserCard user={user} />
      <UserCard name="Jane" age={25} />
    </div>
  );
}

// 子组件
function UserCard({ user, name, age }) {
  const displayName = user ? user.name : name;
  const displayAge = user ? user.age : age;
  
  return (
    <div className="user-card">
      <h2>{displayName}</h2>
      <p>Age: {displayAge}</p>
    </div>
  );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 3. 事件处理

function EventHandling() {
  const [inputValue, setInputValue] = useState('');
  const [items, setItems] = useState([]);

  // 输入处理
  const handleInputChange = (e) => {
    setInputValue(e.target.value);
  };

  // 表单提交
  const handleSubmit = (e) => {
    e.preventDefault();
    if (inputValue.trim()) {
      setItems([...items, inputValue]);
      setInputValue('');
    }
  };

  // 删除项目
  const handleDelete = (index) => {
    setItems(items.filter((_, i) => i !== index));
  };

  return (
    <div>
      <form onSubmit={handleSubmit}>
        <input
          type="text"
          value={inputValue}
          onChange={handleInputChange}
          placeholder="Enter item"
        />
        <button type="submit">Add Item</button>
      </form>
      
      <ul>
        {items.map((item, index) => (
          <li key={index}>
            {item}
            <button onClick={() => handleDelete(index)}>Delete</button>
          </li>
        ))}
      </ul>
    </div>
  );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

# 4. 基础项目实践

# 计数器组件

import { useState } from 'react';

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

  const increment = () => setCount(count + 1);
  const decrement = () => setCount(count - 1);
  const reset = () => setCount(0);

  return (
    <div className="counter">
      <h2>Counter: {count}</h2>
      <div className="buttons">
        <button onClick={decrement}>-</button>
        <button onClick={reset}>Reset</button>
        <button onClick={increment}>+</button>
      </div>
    </div>
  );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 待办事项应用

import { useState } from 'react';

function TodoApp() {
  const [todos, setTodos] = useState([]);
  const [inputValue, setInputValue] = useState('');

  const addTodo = () => {
    if (inputValue.trim()) {
      setTodos([...todos, {
        id: Date.now(),
        text: inputValue,
        completed: false
      }]);
      setInputValue('');
    }
  };

  const toggleTodo = (id) => {
    setTodos(todos.map(todo =>
      todo.id === id ? { ...todo, completed: !todo.completed } : todo
    ));
  };

  const deleteTodo = (id) => {
    setTodos(todos.filter(todo => todo.id !== id));
  };

  return (
    <div className="todo-app">
      <h1>Todo App</h1>
      
      <div className="add-todo">
        <input
          type="text"
          value={inputValue}
          onChange={(e) => setInputValue(e.target.value)}
          onKeyPress={(e) => e.key === 'Enter' && addTodo()}
          placeholder="Add a new todo"
        />
        <button onClick={addTodo}>Add</button>
      </div>

      <ul className="todo-list">
        {todos.map(todo => (
          <li key={todo.id} className={todo.completed ? 'completed' : ''}>
            <input
              type="checkbox"
              checked={todo.completed}
              onChange={() => toggleTodo(todo.id)}
            />
            <span>{todo.text}</span>
            <button onClick={() => deleteTodo(todo.id)}>Delete</button>
          </li>
        ))}
      </ul>
    </div>
  );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58

# 🎣 Hooks 系统

Hooks 是 React 16.8 引入的新特性,让你在函数组件中使用状态和其他 React 特性。

# 1. 基础 Hooks

# useState - 状态管理

import { useState } from 'react';

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

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>+</button>
      <button onClick={() => setCount(count - 1)}>-</button>
      
      <input
        value={name}
        onChange={(e) => setName(e.target.value)}
        placeholder="Enter name"
      />
      <p>Hello, {name}!</p>
    </div>
  );
}

// 复杂状态管理
function UserProfile() {
  const [user, setUser] = useState({
    name: '',
    email: '',
    age: 0
  });

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

  return (
    <div>
      <input
        value={user.name}
        onChange={(e) => updateUser('name', e.target.value)}
        placeholder="Name"
      />
      <input
        value={user.email}
        onChange={(e) => updateUser('email', e.target.value)}
        placeholder="Email"
      />
      <input
        type="number"
        value={user.age}
        onChange={(e) => updateUser('age', parseInt(e.target.value))}
        placeholder="Age"
      />
    </div>
  );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58

# useEffect - 副作用处理

import { useState, useEffect } from 'react';

function DataFetcher() {
  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('https://api.example.com/data');
        const result = await response.json();
        setData(result);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, []); // 空依赖数组,只在挂载时执行

  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error}</div>;
  return <div>Data: {JSON.stringify(data)}</div>;
}

// 带依赖的 useEffect
function UserProfile({ userId }) {
  const [user, setUser] = useState(null);

  useEffect(() => {
    // 当 userId 改变时重新获取数据
    const fetchUser = async () => {
      const response = await fetch(`/api/users/${userId}`);
      const userData = await response.json();
      setUser(userData);
    };

    if (userId) {
      fetchUser();
    }
  }, [userId]); // 依赖 userId

  return user ? <div>{user.name}</div> : <div>Loading...</div>;
}

// 清理副作用
function Timer() {
  const [seconds, setSeconds] = useState(0);

  useEffect(() => {
    const interval = setInterval(() => {
      setSeconds(prev => prev + 1);
    }, 1000);

    // 清理函数
    return () => clearInterval(interval);
  }, []);

  return <div>Timer: {seconds}s</div>;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65

# useContext - 上下文使用

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

// 创建上下文
const ThemeContext = createContext();

// 提供者组件
function ThemeProvider({ children }) {
  const [theme, setTheme] = useState('light');

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

  return (
    <ThemeContext.Provider value={{ theme, toggleTheme }}>
      {children}
    </ThemeContext.Provider>
  );
}

// 使用上下文的组件
function ThemedButton() {
  const { theme, toggleTheme } = useContext(ThemeContext);

  return (
    <button
      onClick={toggleTheme}
      style={{
        backgroundColor: theme === 'light' ? '#fff' : '#333',
        color: theme === 'light' ? '#333' : '#fff'
      }}
    >
      Toggle Theme
    </button>
  );
}

// 应用组件
function App() {
  return (
    <ThemeProvider>
      <ThemedButton />
    </ThemeProvider>
  );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

# 2. 高级 Hooks

# useCallback - 函数缓存

减少可能的重新渲染。 skipping-re-rendering-of-components (opens new window)

import { useState, useCallback, memo } from 'react';

// 子组件
const ExpensiveChild = memo(({ onClick, data }) => {
  console.log('ExpensiveChild rendered');
  return (
    <div>
      <p>Data: {data}</p>
      <button onClick={onClick}>Click me</button>
    </div>
  );
});

// 父组件
function Parent() {
  const [count, setCount] = useState(0);
  const [name, setName] = useState('');

  // 使用 useCallback 缓存函数
  const handleClick = useCallback(() => {
    console.log('Button clicked');
  }, []); // 空依赖数组,函数不会重新创建

  return (
    <div>
      <input
        value={name}
        onChange={(e) => setName(e.target.value)}
        placeholder="Enter name"
      />
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      
      <ExpensiveChild onClick={handleClick} data={name} />
    </div>
  );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

# useMemo - 值缓存

import { useState, useMemo } from 'react';

function ExpensiveCalculation() {
  const [count, setCount] = useState(0);
  const [items, setItems] = useState([]);

  // 使用 useMemo 缓存计算结果
  const expensiveValue = useMemo(() => {
    console.log('Calculating expensive value...');
    return items.reduce((sum, item) => sum + item.value, 0);
  }, [items]); // 只有当 items 改变时才重新计算

  const addItem = () => {
    setItems([...items, { value: Math.random() * 100 }]);
  };

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      
      <p>Items: {items.length}</p>
      <button onClick={addItem}>Add Item</button>
      
      <p>Expensive Value: {expensiveValue}</p>
    </div>
  );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

# useRef - 引用管理

import { useRef, useEffect } from 'react';

function RefExample() {
  const inputRef = useRef(null);
  const countRef = useRef(0);

  useEffect(() => {
    // 聚焦到输入框
    inputRef.current?.focus();
  }, []);

  const handleClick = () => {
    // 使用 ref 访问 DOM 元素
    inputRef.current?.focus();
    
    // 使用 ref 存储可变值
    countRef.current += 1;
    console.log('Click count:', countRef.current);
  };

  return (
    <div>
      <input ref={inputRef} placeholder="Focus me" />
      <button onClick={handleClick}>Focus Input</button>
    </div>
  );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# useReducer - 复杂状态管理

import { useReducer } from 'react';

// 定义 reducer
function todoReducer(state, action) {
  switch (action.type) {
    case 'ADD_TODO':
      return [...state, {
        id: Date.now(),
        text: action.text,
        completed: false
      }];
    case 'TOGGLE_TODO':
      return state.map(todo =>
        todo.id === action.id
          ? { ...todo, completed: !todo.completed }
          : todo
      );
    case 'DELETE_TODO':
      return state.filter(todo => todo.id !== action.id);
    default:
      return state;
  }
}

function TodoApp() {
  const [todos, dispatch] = useReducer(todoReducer, []);
  const [inputValue, setInputValue] = useState('');

  const addTodo = () => {
    if (inputValue.trim()) {
      dispatch({ type: 'ADD_TODO', text: inputValue });
      setInputValue('');
    }
  };

  const toggleTodo = (id) => {
    dispatch({ type: 'TOGGLE_TODO', id });
  };

  const deleteTodo = (id) => {
    dispatch({ type: 'DELETE_TODO', id });
  };

  return (
    <div>
      <input
        value={inputValue}
        onChange={(e) => setInputValue(e.target.value)}
        onKeyPress={(e) => e.key === 'Enter' && addTodo()}
      />
      <button onClick={addTodo}>Add Todo</button>
      
      <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)}>Delete</button>
          </li>
        ))}
      </ul>
    </div>
  );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70

# 3. 自定义 Hooks

# 常用自定义 Hooks

// 自定义 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);
        const result = await response.json();
        setData(result);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, [url]);

  return { data, loading, error };
}

// 使用自定义 Hook
function UserProfile({ userId }) {
  const { data: user, loading, error } = useFetch(`/api/users/${userId}`);

  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error}</div>;
  return <div>{user?.name}</div>;
}

// 自定义 Hook:本地存储
function useLocalStorage(key, initialValue) {
  const [storedValue, setStoredValue] = useState(() => {
    try {
      const item = window.localStorage.getItem(key);
      return item ? JSON.parse(item) : initialValue;
    } catch (error) {
      return initialValue;
    }
  });

  const setValue = (value) => {
    try {
      setStoredValue(value);
      window.localStorage.setItem(key, JSON.stringify(value));
    } catch (error) {
      console.error(error);
    }
  };

  return [storedValue, setValue];
}

// 使用本地存储 Hook
function Settings() {
  const [theme, setTheme] = useLocalStorage('theme', 'light');
  const [language, setLanguage] = useLocalStorage('language', 'en');

  return (
    <div>
      <select value={theme} onChange={(e) => setTheme(e.target.value)}>
        <option value="light">Light</option>
        <option value="dark">Dark</option>
      </select>
      
      <select value={language} onChange={(e) => setLanguage(e.target.value)}>
        <option value="en">English</option>
        <option value="zh">中文</option>
      </select>
    </div>
  );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77

# 🔄 状态管理

# 1. Redux Toolkit

Redux Toolkit 是 Redux 的官方推荐工具集,简化了 Redux 的使用。

# 安装和配置

npm install @reduxjs/toolkit react-redux
1

# Store 配置

// store/index.js
import { configureStore } from '@reduxjs/toolkit';
import counterSlice from './slices/counterSlice';
import userSlice from './slices/userSlice';

export const store = configureStore({
  reducer: {
    counter: counterSlice,
    user: userSlice,
  },
});

export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# Slice 创建

// store/slices/counterSlice.js
import { createSlice } from '@reduxjs/toolkit';

const counterSlice = createSlice({
  name: 'counter',
  initialState: {
    value: 0,
  },
  reducers: {
    increment: (state) => {
      state.value += 1;
    },
    decrement: (state) => {
      state.value -= 1;
    },
    incrementByAmount: (state, action) => {
      state.value += action.payload;
    },
  },
});

export const { increment, decrement, incrementByAmount } = counterSlice.actions;
export default counterSlice.reducer;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 异步操作

// store/slices/userSlice.js
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';

// 异步 thunk
export const fetchUser = createAsyncThunk(
  'user/fetchUser',
  async (userId) => {
    const response = await fetch(`/api/users/${userId}`);
    return response.json();
  }
);

const userSlice = createSlice({
  name: 'user',
  initialState: {
    user: null,
    loading: false,
    error: null,
  },
  reducers: {
    clearUser: (state) => {
      state.user = null;
    },
  },
  extraReducers: (builder) => {
    builder
      .addCase(fetchUser.pending, (state) => {
        state.loading = true;
      })
      .addCase(fetchUser.fulfilled, (state, action) => {
        state.loading = false;
        state.user = action.payload;
      })
      .addCase(fetchUser.rejected, (state, action) => {
        state.loading = false;
        state.error = action.error.message;
      });
  },
});

export const { clearUser } = userSlice.actions;
export default userSlice.reducer;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

# 在组件中使用

// components/Counter.jsx
import { useSelector, useDispatch } from 'react-redux';
import { increment, decrement, incrementByAmount } from '../store/slices/counterSlice';

function Counter() {
  const count = useSelector((state) => state.counter.value);
  const dispatch = useDispatch();

  return (
    <div>
      <span>{count}</span>
      <button onClick={() => dispatch(increment())}>+</button>
      <button onClick={() => dispatch(decrement())}>-</button>
      <button onClick={() => dispatch(incrementByAmount(5))}>+5</button>
    </div>
  );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 2. Zustand

Zustand 是一个轻量级的状态管理库,API 简洁易用。

# 安装

npm install zustand
1

# 创建 Store

// store/useStore.js
import { create } from 'zustand';

const useStore = create((set) => ({
  count: 0,
  increment: () => set((state) => ({ count: state.count + 1 })),
  decrement: () => set((state) => ({ count: state.count - 1 })),
  reset: () => set({ count: 0 }),
}));

export default useStore;
1
2
3
4
5
6
7
8
9
10
11

# 在组件中使用

// components/Counter.jsx
import useStore from '../store/useStore';

function Counter() {
  const { count, increment, decrement, reset } = useStore();

  return (
    <div>
      <span>{count}</span>
      <button onClick={increment}>+</button>
      <button onClick={decrement}>-</button>
      <button onClick={reset}>Reset</button>
    </div>
  );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 3. Context + useReducer

使用 React 内置的状态管理方案。

// context/AppContext.js
import { createContext, useContext, useReducer } from 'react';

const AppContext = createContext();

// Reducer
function appReducer(state, action) {
  switch (action.type) {
    case 'SET_USER':
      return { ...state, user: action.payload };
    case 'SET_LOADING':
      return { ...state, loading: action.payload };
    case 'SET_ERROR':
      return { ...state, error: action.payload };
    default:
      return state;
  }
}

// Provider
export function AppProvider({ children }) {
  const [state, dispatch] = useReducer(appReducer, {
    user: null,
    loading: false,
    error: null,
  });

  return (
    <AppContext.Provider value={{ state, dispatch }}>
      {children}
    </AppContext.Provider>
  );
}

// Hook
export function useApp() {
  const context = useContext(AppContext);
  if (!context) {
    throw new Error('useApp must be used within AppProvider');
  }
  return context;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

# ⚡ 性能优化

# 1. React.memo

import { memo } from 'react';

// 使用 memo 包装组件
const ExpensiveComponent = memo(({ data, onClick }) => {
  console.log('ExpensiveComponent rendered');
  return (
    <div>
      <p>{data}</p>
      <button onClick={onClick}>Click me</button>
    </div>
  );
});

// 自定义比较函数
const MyComponent = memo(({ user }) => {
  return <div>{user.name}</div>;
}, (prevProps, nextProps) => {
  return prevProps.user.id === nextProps.user.id;
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 2. useMemo 和 useCallback

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

function ExpensiveComponent({ items, filter }) {
  // 缓存计算结果
  const filteredItems = useMemo(() => {
    console.log('Filtering items...');
    return items.filter(item => item.category === filter);
  }, [items, filter]);

  // 缓存函数
  const handleClick = useCallback((id) => {
    console.log('Item clicked:', id);
  }, []);

  return (
    <div>
      {filteredItems.map(item => (
        <div key={item.id} onClick={() => handleClick(item.id)}>
          {item.name}
        </div>
      ))}
    </div>
  );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 3. 代码分割和懒加载

import { lazy, Suspense } from 'react';

// 懒加载组件
const LazyComponent = lazy(() => import('./LazyComponent'));

function App() {
  return (
    <div>
      <Suspense fallback={<div>Loading...</div>}>
        <LazyComponent />
      </Suspense>
    </div>
  );
}

// 路由级别的代码分割
import { lazy } from 'react';
import { Routes, Route } from 'react-router-dom';

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

function App() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
      </Routes>
    </Suspense>
  );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

# 🚀 实战项目

# 电商购物车应用

// components/Cart.jsx
import { useState, useMemo } from 'react';

function Cart() {
  const [items, setItems] = useState([
    { id: 1, name: 'Product 1', price: 10, quantity: 1 },
    { id: 2, name: 'Product 2', price: 20, quantity: 2 },
  ]);

  const total = useMemo(() => {
    return items.reduce((sum, item) => sum + item.price * item.quantity, 0);
  }, [items]);

  const updateQuantity = (id, quantity) => {
    setItems(items.map(item =>
      item.id === id ? { ...item, quantity } : item
    ));
  };

  const removeItem = (id) => {
    setItems(items.filter(item => item.id !== id));
  };

  return (
    <div className="cart">
      <h2>Shopping Cart</h2>
      {items.map(item => (
        <div key={item.id} className="cart-item">
          <span>{item.name}</span>
          <span>${item.price}</span>
          <input
            type="number"
            value={item.quantity}
            onChange={(e) => updateQuantity(item.id, parseInt(e.target.value))}
            min="1"
          />
          <button onClick={() => removeItem(item.id)}>Remove</button>
        </div>
      ))}
      <div className="total">Total: ${total}</div>
    </div>
  );
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

# ❓ 常见问题

# Q1: 什么时候使用 useCallback 和 useMemo?

A: 使用场景:

  • useCallback: 当函数作为 props 传递给子组件时
  • useMemo: 当有昂贵的计算需要缓存时
  • 注意: 不要过度使用,只在真正需要时使用

# Q2: 如何避免不必要的重新渲染?

A: 优化策略:

  • 使用 React.memo 包装组件
  • 使用 useCallback 缓存函数
  • 使用 useMemo 缓存计算结果
  • 避免在 render 中创建新对象

# Q3: 如何处理异步数据获取?

A: 推荐方案:

// 使用自定义 Hook
function useAsyncData(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);
        const result = await response.json();
        setData(result);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, [url]);

  return { data, loading, error };
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# Q4: 如何调试 React 应用?

A: 调试工具:

  • React Developer Tools: 浏览器扩展
  • console.log: 在组件中添加日志
  • React.StrictMode: 开发模式下启用严格模式
  • Error Boundaries: 捕获和处理错误

# Q5: 如何优化大型列表的性能?

A: 优化方案:

  • 使用虚拟化列表(react-window, react-virtualized)
  • 使用 React.memo 优化列表项
  • 实现分页或无限滚动
  • 使用 key 属性优化列表渲染

# 📚 学习资源

# 官方文档

  • React 官方文档 (opens new window) - 最新的 React 官方文档
  • React 中文文档 (opens new window) - 中文版官方文档
  • React 参考 (opens new window) - API 参考文档
  • React Native (opens new window) - 移动端开发

# 在线教程

  • React 官方教程 (opens new window) - 官方交互式教程
  • React 实战教程 (opens new window) - 深度实战教程
  • React 模式 (opens new window) - React 设计模式
  • React 最佳实践 (opens new window) - 官方最佳实践

# 工具和库

  • Create React App (opens new window) - 官方脚手架工具
  • Vite (opens new window) - 快速构建工具
  • Redux Toolkit (opens new window) - 状态管理工具
  • React Router (opens new window) - 路由管理
  • React Query (opens new window) - 数据获取库

# 社区资源

  • React 官方论坛 (opens new window) - 官方讨论社区
  • Stack Overflow React 标签 (opens new window) - 技术问答
  • Reddit r/reactjs (opens new window) - Reddit 社区
  • React 中文社区 (opens new window) - 中文开发者社区

# 实践项目

  • React 项目集合 (opens new window) - 个人项目集合
  • React 示例代码 (opens new window) - 代码示例
  • React 最佳实践 (opens new window) - 最佳实践代码

# 🎯 学习建议

# 时间安排

  • 每日学习时间: 2-4小时
  • 每周项目实践: 至少一个完整项目
  • 定期复习: 每周末回顾本周学习内容

# 学习方法

  1. 理论结合实践: 每学一个概念就动手实现
  2. 项目驱动: 通过完整项目巩固知识点
  3. 社区参与: 参与开源项目和技术讨论
  4. 持续学习: 关注React生态发展,保持技术更新

# 技能评估

  • 基础阶段: 能够独立开发简单组件
  • 进阶阶段: 掌握 Hooks 和组件通信
  • 高级阶段: 熟练使用状态管理和性能优化
  • 实战阶段: 能够独立完成复杂项目

# 🎉 总结

通过本指南的学习,你已经掌握了:

  1. React 基础 - 理解了组件、JSX、状态管理等核心概念
  2. Hooks 系统 - 学会了使用现代 React 开发模式
  3. 状态管理 - 掌握了 Redux、Zustand 等状态管理方案
  4. 性能优化 - 学会了优化 React 应用性能
  5. 实战项目 - 完成了完整的 React 应用开发

# 下一步学习建议

  1. 深入学习 TypeScript - 提升代码质量和开发效率
  2. 学习测试 - 掌握 Jest 和 React Testing Library
  3. 探索 React 生态 - 学习 Next.js、Gatsby 等框架
  4. 参与开源项目 - 提升实际开发经验

# 记住这些要点

  • 实践是最好的老师 - 多写代码、多调试、多思考
  • 理解原理 - 不要只停留在使用层面,要理解背后的原理
  • 社区参与 - 积极参与社区讨论,分享经验

React 是现代前端开发的核心技术之一,掌握它将为你的职业发展带来巨大帮助。继续深入学习,探索更多可能性!🚀

#React#tutorial
上次更新: 2025/10/09, 22:57:36
vue base
React Hooks 完整指南

← vue base React Hooks 完整指南→

最近更新
01
npx 使用指南
10-12
02
cursor
09-28
03
inspect
07-20
更多文章>
Theme by Vdoing | Copyright © 2019-2025 Jacky | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式