本课是 React 开发的核心进阶课程,聚焦 React Hooks 函数式编程体系。Hooks 彻底改变了 React 开发模式,让函数组件拥有状态与副作用能力,代码更简洁、逻辑更聚合。课程从基础 useState、useEffect、useRef 到性能优化 useMemo、useCallback,再到自定义 Hooks 封装,全面覆盖企业级 React 必备技能。通过单词实战案例,将状态管理、异步请求、DOM 操作、逻辑复用串联起来,帮助建立函数式编程思维。掌握本课内容,可独立开发标准 React 项目,轻松对接接口、处理副作用、优化性能,是 React 从入门到实战的关键一课。
一、课程学习目的
-
深入理解 React Hooks 的设计理念与核心作用,掌握函数式组件的状态与副作用管理。
-
熟练掌握常用 Hooks:
useState、useEffect、useRef、useMemo、useCallback。 -
学会自定义 Hooks 封装复用逻辑,提升代码模块化与可维护性。
-
掌握 React 性能优化基础手段,避免无效渲染。
-
能够使用 Hooks 完成完整实战项目,对接异步请求与业务逻辑。
-
建立 React 函数式编程思维,适配企业级 React 开发标准。
二、核心知识点讲解
1. React Hooks 概述
Hooks 是 React 16.8 推出的特性,让函数式组件拥有状态、生命周期、副作用等能力,彻底替代类组件。
Hooks 只能在函数组件顶层使用,不能在循环、条件、普通函数中调用。
优势:代码更简洁、逻辑更聚合、复用性更强、易于测试。
2. 基础必备 Hooks
-
useState:组件状态管理,修改状态自动触发视图更新。
-
useEffect:副作用处理(异步请求、定时器、DOM 操作)。
-
useRef:获取 DOM 元素、存储跨渲染数据。
-
useMemo:缓存计算结果,避免重复计算。
-
useCallback:缓存函数,避免子组件重复渲染。
3. 自定义 Hooks
自定义 Hooks 是以 use 开头的函数,内部可调用其他 Hooks,用于封装可复用逻辑(如请求、表单、定时器)。
作用:抽离公共逻辑、简化组件、提高可读性。
4. useEffect 依赖规则
-
空数组
[]:仅挂载、卸载时执行一次。 -
带依赖
[a,b]:依赖变化时执行。 -
无依赖:每次渲染都执行。
-
必须正确处理依赖,避免死循环。
5. React 状态更新规则
状态不可直接修改,必须通过set 函数返回新值。
对象/数组需使用展开语法创建新引用。
三、示例程序(带详细注释)
示例1:useState + useEffect 异步请求
JavaScript
import { useState, useEffect } from 'react'
function WordList() {
// 状态管理
const [wordList, setWordList] = useState([])
const [loading, setLoading] = useState(false)
// 副作用:页面加载请求数据
useEffect(() => {
async function getList() {
setLoading(true)
// 模拟请求
const res = await new Promise(r => setTimeout(() => r([
{ en: 'book', cn: '书' },
{ en: 'pen', cn: '笔' }
]), 1000))
setWordList(res)
setLoading(false)
}
getList()
}, []) // 空依赖 → 只执行一次
return (
<div>
{loading && <p>加载中...</p>}
{wordList.map((item, i) => (
<div key={i}>{item.en} - {item.cn}</div>
))}
</div>
)
}
示例2:useRef 获取 DOM
JavaScript
import { useRef } from 'react'
function InputFocus() {
const inputRef = useRef(null)
const focus = () => {
// 操作原生 DOM
inputRef.current.focus()
}
return (
<div>
<input ref={inputRef} />
<button onClick={focus}>聚焦</button>
</div>
)
}
示例3:自定义 Hooks(封装单词请求)
JavaScript
// hooks/useWord.js
import { useState, useEffect } from 'react'
// 自定义 Hook
export function useWord() {
const [wordList, setWordList] = useState([])
useEffect(() => {
setTimeout(() => {
setWordList([{ en: 'react', cn: 'React' }])
}, 800)
}, [])
return wordList
}
// 组件中使用
function App() {
const wordList = useWord()
return <div>{wordList.map(i => <div key={i.en}>{i.en}</div>)}</div>
}
示例4:useMemo 缓存计算
JavaScript
import { useMemo } from 'react'
function totalWord(wordList) {
console.log('计算总数')
return wordList.length
}
function App({ wordList }) {
// 缓存结果,只有 wordList 变化才重新计算
const count = useMemo(() => totalWord(wordList), [wordList])
return <div>总数:{count}</div>
}
四、掌握技巧与方法
-
Hooks 必须在函数顶层调用,不能在 if / for / 普通函数里使用。
-
useEffect 必须正确配置依赖,避免死循环或不执行。
-
状态不可变:不能直接 push / splice,必须返回新数组/对象。
-
公共逻辑抽离为自定义 Hooks,实现逻辑复用。
-
useRef 可存储任何不需要触发渲染的数据。
-
useMemo / useCallback 用于性能优化,不要过度使用。
-
异步请求必须放在 useEffect 或自定义 Hooks 中。
五、课后作业
基础作业
-
使用 useState + useEffect 实现单词列表异步加载,展示 loading 状态。
-
使用 useRef 获取输入框 DOM,实现按钮自动聚焦。
-
了解 useMemo 缓存计算结果的用法。
进阶作业
-
封装一个自定义 Hook,用于获取单词列表数据。
-
实现单词搜索功能,输入关键词实时过滤列表。
-
使用 useEffect 清理定时器/订阅,防止内存泄漏。
实战作业
- 开发 React 单词搜索系统:包含异步加载、搜索过滤、状态管理、自定义 Hooks,完整可运行。
上一课:前端框架实战(React 基础)实战作业代码
代码功能说明
本实战作业基于 Vite + React 开发单词管理系统,使用函数式组件与 JSX 语法,通过 useState 管理响应式状态(单词列表、输入框内容),实现添加、删除单词核心功能;利用 useEffect 在组件挂载时打印初始化日志;通过 Props 将单词数据传递给子组件展示,完成组件通信。页面包含输入框、操作按钮、列表渲染、空状态提示,符合 React 基础开发规范,完整覆盖 JSX、组件拆分、状态管理、事件处理、列表渲染等核心知识点,帮助快速掌握 React 基础开发流程。
注意事项
-
必须安装 Node.js 环境,使用 npm 安装依赖。
-
React 使用 className 代替 class,style 需写成对象格式。
-
状态不可直接修改,必须使用 set 函数生成新值。
-
列表渲染 key 必须唯一,建议使用唯一 id,不推荐仅用 index。
-
组件名必须大写,文件后缀建议使用 .jsx。
-
运行命令:npm install → npm run dev。
-
禁止在 return 中直接修改状态,会导致无限渲染。
完整实战代码
项目结构
Plain
react-word-demo/
├── index.html
├── package.json
└── src/
├── main.jsx
├── App.jsx
├── components/
│ └── WordItem.jsx
└── index.css
src/main.jsx
JavaScript
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
import './index.css'
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<App />
</React.StrictMode>
)
src/App.jsx
JavaScript
import { useState, useEffect } from 'react'
import WordItem from './components/WordItem'
function App() {
const [wordList, setWordList] = useState([
{ en: 'apple', cn: '苹果' },
{ en: 'banana', cn: '香蕉' }
])
const [inputEn, setInputEn] = useState('')
const [inputCn, setInputCn] = useState('')
useEffect(() => {
console.log('单词管理器已初始化')
}, [])
const addWord = () => {
if (!inputEn || !inputCn) return
setWordList([...wordList, { en: inputEn, cn: inputCn }])
setInputEn('')
setInputCn('')
}
const delWord = (index) => {
const newList = [...wordList]
newList.splice(index, 1)
setWordList(newList)
}
return (
<div className="app">
<h2>React 单词管理器</h2>
<div className="input-box">
<input
type="text"
placeholder="英文"
value={inputEn}
onChange={(e) => setInputEn(e.target.value)}
/>
<input
type="text"
placeholder="中文"
value={inputCn}
onChange={(e) => setInputCn(e.target.value)}
/>
<button onClick={addWord}>添加</button>
</div>
<div className="list">
{wordList.length === 0 ? (
<p className="empty">暂无单词</p>
) : (
wordList.map((item, index) => (
<WordItem
key={index}
item={item}
index={index}
delWord={delWord}
/>
))
)}
</div>
</div>
)
}
export default App
src/components/WordItem.jsx
JavaScript
export default function WordItem({ item, index, delWord }) {
return (
<div className="word-item">
<span>{item.en} --- {item.cn}</span>
<button onClick={() => delWord(index)}>删除</button>
</div>
)
}
src/index.css
CSS
.app {
max-width: 600px;
margin: 30px auto;
padding: 20px;
}
.input-box {
margin: 20px 0;
}
input {
padding: 8px;
margin-right: 6px;
}
button {
padding: 8px 12px;
background: #61dafb;
border: none;
cursor: pointer;
border-radius: 4px;
}
.word-item {
padding: 10px;
background: #f5f5f5;
margin: 6px 0;
display: flex;
justify-content: space-between;
border-radius: 4px;
}
.empty {
color: #999;
padding: 20px 0;
text-align: center;
}
运行命令
Bash
npm install
npm run dev
作业验收标准
-
项目可正常启动,无报错。
-
可添加、删除单词,视图实时更新。
-
空数据时展示空状态。
-
使用 useState、useEffect 正确。
-
组件拆分清晰,Props 传参正常。
-
代码规范、注释清晰、符合 React 基础标准。