Hooks
使用规则
- 只能在函数组件或自定义 Hook 的顶层调用
不能在条件判断、循环、嵌套函数中调用,确保 Hook 调用顺序一致。 - 自定义 Hook 命名必须以
use
开头
例如useState
、useFetch
等,方便区分普通函数和 Hook。
常用的 React Hooks
React 提供了多种内置的 Hooks,常用的包括:
useState
:用于在函数组件中添加状态。useEffect
:用于处理副作用,如数据获取、订阅或手动 DOM 操作。useContext
:用于在组件中订阅 React 上下文。useReducer
:用于以 reducer 的方式管理复杂的状态逻辑。useRef
:用于访问 DOM 节点或保存可变值。useMemo
:用于缓存计算结果,优化性能。useCallback
:用于缓存函数实例,避免不必要的重新渲染。
useState
与 useEffect
作用
useState
用来管理组件内部状态,返回当前状态和更新状态的函数。
1 | const [count, setCount] = useState(0); |
count
是当前状态值,setCount
是更新函数。
useEffect
用于处理副作用,比如数据请求、DOM 操作、订阅等。
可以模拟类组件的生命周期:
1 | useEffect(() => { |
useMemo
与 useCallback
区别
useMemo
缓存计算结果,避免因每次渲染导致的重复计算。1
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
useCallback
缓存函数的引用,避免子组件因函数引用变化而重复渲染。1
2
3const memoizedCallback = useCallback(() => {
doSomething(a, b);
}, [a, b]);
性能优化
一、如何避免不必要的重渲染
React 组件的重新渲染会带来性能开销,避免无谓的重渲染是优化的关键。常用方法有:
1. 使用
React.memo
缓存组件React.memo
是高阶组件,类似于类组件的PureComponent
,对函数组件进行浅层 props 比较,只有 props 变化才重新渲染。示例:
1
2
3
4const MyComponent = React.memo(({ value }) => {
console.log('render');
return <div>{value}</div>;
});适合传入简单数据的组件,复杂对象需要注意浅比较的局限。
2. 使用
useCallback
缓存函数引用避免每次渲染都创建新的函数,导致子组件因 props 变化重新渲染。
示例:
1
2
3
4
5
6
7
8const Parent = () => {
const [count, setCount] = useState(0);
const handleClick = useCallback(() => {
setCount(c => c + 1);
}, []);
return <Child onClick={handleClick} />;
}这样
Child
组件不会因为每次渲染都拿到新的函数引用而重复渲染。
3. 使用
useMemo
缓存计算结果避免每次渲染都执行复杂计算,导致子组件因传入新对象或新数据而重新渲染。
示例:
1
const expensiveResult = useMemo(() => computeExpensive(data), [data]);
4. 拆分组件
- 将大组件拆成多个小组件,减少状态变化时渲染范围。
二、React.lazy 与 Suspense 的作用
1.
React.lazy
用于实现组件的动态按需加载(代码分割),减小首屏加载体积。
只有当组件真正需要渲染时才去加载对应的 JS 代码。
示例:
1
2
3
4
5
6
7
8
9
10
11import React, { lazy, Suspense } from 'react';
const LazyComponent = lazy(() => import('./LazyComponent'));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</Suspense>
);
}
2.
Suspense
- 用于包裹
React.lazy
异步加载的组件,指定加载中的占位 UI(如加载动画或提示文字)。 - 当异步组件未加载完成时,会展示
fallback
指定的内容。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23import React, { Suspense, lazy, useState } from 'react';
// 使用 React.lazy 动态导入组件
const LazyComponent = lazy(() => import('./LazyComponent'));
function App() {
const [show, setShow] = useState(false);
return (
<div>
<button onClick={() => setShow(true)}>显示懒加载组件</button>
{/* Suspense 包裹懒加载组件,fallback 显示加载时内容 */}
{show && (
<Suspense fallback={<div>加载中,请稍候...</div>}>
<LazyComponent />
</Suspense>
)}
</div>
);
}
export default App;总结
React.lazy
+Suspense
可以有效实现按需加载,提升应用性能,尤其适合大型应用和路由懒加载。