React笔记
2025年7月3日 14:57
React Hooks
1. useState
用于在函数组件中添加状态管理功能。它让函数组件能够拥有自己的内部状态。
(1)基本语法
const [state, setState] = useState(initialValue);
-
state
: 当前状态值 -
setState
: 更新状态的函数 -
initialValue
: 状态的初始值
(2)重要特性
- 状态更新是异步的
function AsyncExample() {
const [count, setCount] = useState(0);
const handleClick = () => {
console.log('点击前:', count); // 0
setCount(count + 1);
console.log('点击后:', count); // 仍然是 0,因为状态更新是异步的
};
return (
<div>
<p>Count: {count}</p>
<button onClick={handleClick}>增加</button>
</div>
);
}
- 函数式更新:当新状态依赖于前一个状态时,需使用函数式更新:
function Counter() {
const [count, setCount] = useState(0);
const incrementTwice = () => {
// 错误方式:可能不会按预期工作
// setCount(count + 1);
// setCount(count + 1);
// 正确方式:使用函数式更新
setCount(prevCount => prevCount + 1);
setCount(prevCount => prevCount + 1);
};
return (
<div>
<p>Count: {count}</p>
<button onClick={incrementTwice}>增加2</button>
</div>
);
}
- React 会对多个状态更新进行批处理:
function BatchingExample() {
const [count, setCount] = useState(0);
const [flag, setFlag] = useState(false);
const handleClick = () => {
// 这些更新会被批处理,只触发一次重新渲染
setCount(c => c + 1);
setFlag(f => !f);
};
console.log('渲染'); // 只会打印一次
return (
<div>
<p>Count: {count}</p>
<p>Flag: {flag.toString()}</p>
<button onClick={handleClick}>更新</button>
</div>
);
}
2. useEffect
用于处理副作用,包括:请求数据、设置订阅、操作 DOM、定时器、清理资源。
(1)基本语法
useEffect(() => {
console.log('组件挂载或更新');
return () => {
console.log('组件卸载或清理');
};
}, [count]); // 依赖项改变时才执行
第二个参数是依赖数组: 空数组 []
时,只在挂载时执行一次;有依赖项时,依赖项变化时执行;无依赖数组时,每次渲染都执行。
(2)在return 中,可以取消请求、清理定时器、移除事件监听器
// 取消请求
function SearchResults({ query }) {
const [results, setResults] = useState([]);
const [loading, setLoading] = useState(false);
useEffect(() => {
if (!query) {
setResults([]);
return;
}
const abortController = new AbortController();
const searchData = async () => {
try {
setLoading(true);
const response = await fetch(`/api/search?q=${query}`, {
signal: abortController.signal
});
const data = await response.json();
setResults(data);
} catch (error) {
if (error.name !== 'AbortError') {
console.error('搜索失败:', error);
}
} finally {
setLoading(false);
}
};
searchData();
// 清理函数:取消请求
return () => {
abortController.abort();
};
}, [query]);
return (
<div>
{loading && <div>搜索中...</div>}
<ul>
{results.map(item => (
<li key={item.id}>{item.title}</li>
))}
</ul>
</div>
);
}
3. useContext
用于在组件树中跨层级传递数据,避免了逐层传递 props的问题。能够在不通过 props 的情况下,将数据传递给深层嵌套的组件。
- Context: 上下文对象,用于存储共享数据
- Provider: 提供者组件,用于提供数据
- Consumer: 消费者组件,用于使用数据
import React, { createContext, useContext, useState } from 'react';
// 1. 创建 Context
const ThemeContext = createContext();
// 2. 创建 Provider 组件
function ThemeProvider({ children }) {
const [theme, setTheme] = useState('light');
const toggleTheme = () => {
setTheme(prevTheme => prevTheme === 'light' ? 'dark' : 'light');
};
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
}
// 3. 在子组件中使用 Context
function Header() {
const { theme, toggleTheme } = useContext(ThemeContext);
return (
<header style={{
backgroundColor: theme === 'light' ? '#fff' : '#333',
color: theme === 'light' ? '#333' : '#fff'
}}>
<h1>我的应用</h1>
<button onClick={toggleTheme}>
切换到 {theme === 'light' ? '深色' : '浅色'} 模式
</button>
</header>
);
}
function Content() {
const { theme } = useContext(ThemeContext);
return (
<main style={{
backgroundColor: theme === 'light' ? '#f5f5f5' : '#222',
color: theme === 'light' ? '#333' : '#fff',
padding: '20px'
}}>
<p>当前主题: {theme}</p>
</main>
);
}
// 4. 在应用中使用
function App() {
return (
<ThemeProvider>
<Header />
<Content />
</ThemeProvider>
);
}
4. useRef
用于获取 DOM 节点或保存可变值,useRef 返回一个对象,该对象有一个 current
属性,可以通过修改 current
来存储任何值。与 useState 不同的是,修改 useRef 的值不会触发组件重新渲染。
function TextInput() {
const inputRef = useRef(null);
const focusInput = () => {
inputRef.current.focus();
};
return (
<div>
<input ref={inputRef} type="text" />
<button onClick={focusInput}>聚焦输入框</button>
</div>
);
}
5. useMemo
可以缓存计算结果,只有在依赖项发生变化时才会重新计算。
(1)基本语法
import { useMemo } from 'react';
const memoizedValue = useMemo(() => {
return expensiveCalculation(a, b);
}, [a, b]);
useMemo 接收两个参数:
- 计算函数:返回需要缓存的值
- 依赖数组:当数组中的值发生变化时,才会重新执行计算函数
6. useCallback
用于缓存函数,返回一个记忆化的回调函数,只有在依赖项发生变化时才会重新创建函数。
import { useCallback } from 'react';
const memoizedCallback = useCallback(() => {
// 函数逻辑
}, [dependency1, dependency2]);
useCallback 接收两个参数:
- 回调函数:需要缓存的函数
- 依赖数组:当数组中的值发生变化时,才会重新创建函数
7. useReducer
useState 的替代方案,特别适用于复杂的状态逻辑管理。
import { useReducer } from 'react';
const [state, dispatch] = useReducer(reducer, initialState);
function Counter() {
const initialState = { count: 0 };
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
case 'reset':
return initialState;
default:
throw new Error();
}
}
const [state, dispatch] = useReducer(reducer, initialState);
return (
<div>
<p>计数: {state.count}</p>
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
<button onClick={() => dispatch({ type: 'reset' })}>重置</button>
</div>
);
}