# 一.react-hooks 的一些坑

此类问题一般会涉及到闭包问题

1.useEffect 包含了哪几个生命周期?

点击查看答案 componentDidMount、componentDidUpdate 、 componentWillUnmount

2.useEffect 在生命时候执行?

点击查看答案 useEffect 会在第一次渲染之后和每次更新渲染之后都会执行,并且在 DOM 渲染结束之后执行

3.useEffect 死循环?

点击查看答案 说明useEffect在传入第二个参数时一定注意:第二个参数不能为引用类型,会造成死循环,比如 `[] === []` 为false,所以会造成useEffect会一直不停的渲染,因此把data的初始值改为undefined,就可以

4.函数作为依赖的时候死循环?(依赖项没指定好)

点击查看答案

(1) 提到组件外面,或者用 useCallback 包一层。useMemo 可以做类似的事情以避免重复生成对象。

子组件:

useEffect(() => {
  props.onChange(props.id);
}, [props.onChange, props.id]);
1
2
3

父组件的 onChange 需要 useCallback 包一层:

const onChange = useCallback(() => {
...
}, [])
1
2
3

(2) 关于 useCallback

怎么使用好 useCallback,来达到减少 render 次数的效果

react 优化方式:减少 render 次数,减少计算量

下面的代码,当 handleClick1 时间触发时,PageB 组件也会重新渲染

import React, { memo, useCallback, useState } from "react";

function PageA(props) {
  const { onClick, children } = props;
  console.log(111, props);
  return <div onClick={onClick}>{children}</div>;
}

function PageB({ onClick, name }) {
  console.log(222);
  return <div onClick={onClick}>{name}</div>;
}
// 使用useCallback写法
const PageC = memo(PageB);

function UseCallback() {
  const [a, setA] = useState(0);
  const [b, setB] = useState(0);

  const handleClick1 = () => {
    setA(a + 1);
  };

  const handleClick2 =
    (() => {
      setB(b + 1);
      // 使用useCallback写法: , [b]
    },
    [b]);

  return (
    <>
      <PageA onClick={handleClick1}>{a}</PageA>
      {/*没使用useCallback写法 */}
      <PageB onClick={handleClick2} name={b} />
      {/*使用useCallback写法 */}
      <PageC onClick={handleClick2} name={b} />
    </>
  );
}

export default UseCallback;
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

使用 useCallback 进行处理:

a. 点击事件 handleClick1 触发时,PageB 组件也会重新渲染,当 PageB 组件比较耗时时,就会造成新能问题

b. PageB 组件重新渲染的原因在于每次重新渲染,onClick 都会重新定义,即上次的与这次的不一致

c. 思路:通过 useCallback 包裹 onClick 来达到缓存的效果,即 useCallback的依赖项不变时不重新生成

d. 用过memo方法包裹 PageB 组件,并且通过 useCallback 包裹 PageB 组件的 onClick 方法,memoPureComponent 比较类似,前者是对 Function Component 的优化,后者是对 Class Component 的优化,都会对传入组件的数据进行浅比较,useCallback 则会保证handleClick2不会发生变化


5.useEffect 里面拿不到最新的 props 和 state?

点击查看答案 使用 refs
function Example() {
const [count, setCount] = useState(0);
const latestCount = useRef(count);

useEffect(() => {
// Set the mutable latest value
latestCount.current = count;
setTimeout(() => {
// Read the mutable latest value
console.log(`You clicked ${latestCount.current} times`);
}, 3000);
})
1
2
3
4
5
6
7
8
9
10
11
12

6.关于闭包的一些问题

点击查看答案

闭包问题经常捕获一个为更新的变量,一个有效的解决闭包问题的方法是在 React hooks 里设置正确的依赖,或者用函数的方式更新 state

详见 (opens new window)


# 参考

https://www.jianshu.com/p/e28a029cfc56