React学习之hooks中的闭包问题以及解决策略,useLatest的使用

Posted by deft on May 27, 2023

react hooks 使用中的闭包问题

案例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import { useState } from 'react'

export default function () {
  const [count, setCount] = useState(0)

  useEffect(() => {
    setInterval(() => {
      console.log('count: ', count)
    }, 1000)
  }, [])

  return (
    <div>
      <p>count: {count}</p>
      <button onClick={() => setCount(v => v + 1)}></button>
    </div>
  )
}

点击按钮修改 count 的值时,发现 setInterval 中打印的值始终为 0,这就是闭包产生的问题。

使用 useLatest 解决此问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import React, { useState, useEffect } from 'react'
import { useLatest } from 'ahooks'

export default () => {
  const [count, setCount] = useState(0)

  const latestCountRef = useLatest(count)

  useEffect(() => {
    const interval = setInterval(() => {
      setCount(latestCountRef.current + 1)
    }, 1000)
    return () => clearInterval(interval)
  }, [])

  return (
    <>
      <p>count: {count}</p>
    </>
  )
}

ahooks 中 useLatest 源码

1
2
3
4
5
6
7
8
9
10
import { useRef } from 'react'

function useLatest<T>(value: T) {
  const ref = useRef(value)
  ref.current = value

  return ref
}

export default useLatest