← 返回目录

第 17 卷

第 17 / 28 卷日期:

(2)useLayoutEffect 的使用场景

useLayoutEffect 仅适用于「必须在绘制前完成」的场景,核心是避免页面闪烁或获取准确的 DOM 布局信息,常见案例:

  • 获取 DOM 布局信息(如宽高、位置)并同步更新状态(如根据 DOM 宽度调整组件样式);
  • 需要在绘制前修正 DOM 状态(如避免元素位置偏移、文字闪烁);
  • 与第三方 DOM 库集成(如某些图表库需要在 DOM 绘制前初始化)。

示例:根据元素宽度调整文字大小(避免闪烁)

Code block

1 2function ResizableText() {

3const [fontSize, setFontSize] = useState(16);

4const textRef = useRef(null);

5 6useLayoutEffect(() => {

7// 绘制前获取 DOM 宽度(准确,因为 DOM 已更新但未绘制)

8const width = textRef.current.offsetWidth;

9

10//根据宽度调整字体大小(同步更新状态,绘制时直接使用新字体大小,无闪烁)
11if (width > 500) {
12setFontSize(24);
13} else if (width < 200) {
14setFontSize(12);
15} else {
16setFontSize(16);
17}
18}, []); //组件挂载时执行一次

19 20return (

21<div ref={textRef} style={{ fontSize: `${fontSize}px` }}>
22这是一段根据容器宽度自适应字体大小的文字
23</div>
24);
25}

• 优先使用 useEffect:useLayoutEffect 会阻塞渲染,可能导致页面卡顿,非必要不使用;仅当

useEffect 无法满足需求(如出现闪烁、需要准确布局信息)时,才考虑 useLayoutEffect。

• 避免长时间任务:useLayoutEffect 的回调函数执行时间过长会严重阻塞页面渲染,应尽量简化逻

辑,复杂计算需移至 useEffect 或 Web Worker 中。

• 服务器端渲染(SSR)注意:useLayoutEffect 在服务器端不会执行(因为服务器端无 DOM 绘制流

程),若组件在 SSR 环境中使用,可能导致客户端与服务器端渲染结果不一致;此时应改用 useEffect,或添加客户端判断。

二十八、使用 React Hooks 时需要遵守哪些限制和规则?

React Hooks 的设计遵循严格的规则,这些规则是为了确保 Hooks 能够正确追踪组件状态、维护执行顺序的稳定性,避免出现不可预测的 bug。违反规则可能导致组件状态错乱、生命周期逻辑异常等问

题,核心规则由 React 官方定义,同时包含一些实践层面的最佳规则。

1. 官方核心规则(必须严格遵守)

(1)只能在函数组件的顶层调用 Hooks

核心要求:Hooks 必须在函数组件的「最顶层作用域」调用,不能在条件判断(if/else)、循环(for/while)、嵌套函数(如函数内部定义的函数)中调用。

原因:React 是通过「Hooks 的调用顺序」来追踪状态的(如第一个 useState 对应第一个状态,第二个 useState 对应第二个状态)。若在条件/循环中调用 Hooks,会导致组件每次渲染时 Hooks 的调用

顺序不一致,React 无法正确关联状态与 Hooks,从而引发状态错乱。

错误示例:

Code block

1 2function BadComponent() {

3const [count, setCount] = useState(0);

4 5// 错误:在条件判断中调用 useEffect

6if (count > 0) { 7useEffect(() => {

8console.log('count 大于 0');

9}, [count]);

10}

12return <button onClick={() => setCount(count + 1)}>{count}</button>;

13}

1 2function GoodComponent() {

3const [count, setCount] = useState(0);

4

5//正确:顶层调用useEffect,在内部判断条件
6useEffect(() => {
7if (count > 0) {
8console.log('count大于0');
9}
10}, [count]);

11 12return <button onClick={() => setCount(count + 1)}>{count}</button>;

13}

(2)只能在 React 函数组件或自定义 Hooks 中调用 Hooks

核心要求:Hooks 不能在普通 JavaScript 函数中调用,只能在两种场景下使用:

  • React 函数组件(定义为函数,返回 JSX 的组件);
  • 自定义 Hooks(命名以 use 开头,内部可调用其他 Hooks 的函数)。

原因:Hooks 依赖 React 的内部机制(如 Fiber 架构、状态追踪系统)来工作,普通 JavaScript 函数不具备这些机制,调用 Hooks 会导致 React 无法追踪状态,进而引发错误。

错误示例:

Code block

1

2//错误:在普通JavaScript函数中调用useState
3function normalJsFunction() {
4const [name, setName] = useState(''); // React无法识别,报错
5return name;
6}

正确示例:

Code block

2// 正确:在自定义 Hooks 中调用 Hooks

全站分卷索引 · 28 卷
  1. 1第 1 卷
  2. 2第 2 卷
  3. 3第 3 卷
  4. 4第 4 卷
  5. 5第 5 卷
  6. 6第 6 卷
  7. 7第 7 卷
  8. 8第 8 卷
  9. 9第 9 卷
  10. 10第 10 卷
  11. 11第 11 卷
  12. 12第 12 卷
  13. 13第 13 卷
  14. 14第 14 卷
  15. 15第 15 卷
  16. 16第 16 卷
  17. 17第 17 卷
  18. 18第 18 卷
  19. 19第 19 卷
  20. 20第 20 卷
  21. 21第 21 卷
  22. 22第 22 卷
  23. 23第 23 卷
  24. 24第 24 卷
  25. 25第 25 卷
  26. 26第 26 卷
  27. 27第 27 卷
  28. 28第 28 卷