如下,增加一个 timeDateG 不是最优雅的方式吧?
import { useEffect, useState } from "react"
let timeDateG = '00:00:00'
const UseStateIssue = () => {
  const [timeDate, setTimeDate] = useState('00:00:00')
  useEffect(()=>{
    timeDateG = timeDate
  }, [timeDate])
  useEffect(()=>{
    const interval = setInterval(()=>{
      console.log('timeDate', timeDate) // 一直是 '00:00:00'
      console.log('timeDateG', timeDateG) // 解决方法 1
    }, 2000)
    return () => clearInterval(interval)
  }, [])
  return (
    <div>
      <div>{timeDate},这里正常刷新</div>
      <button onClick={()=>{
        setTimeDate(new Date().toLocaleTimeString())
        }}>setTimeDate</button>
    </div>
  )
}
export default UseStateIssue
|      1headsteins      2022-10-23 12:01:12 +08:00 使用 useRef 获取 state 的最新值吗?猜测可以用 ref.current = state 这样应该 | 
|  |      2estk OP @headsteins #1 也有考虑过 useRef ,感觉这样跟多个全局变量差别不大 | 
|  |      3kkocdko      2022-10-23 13:04:56 +08:00 因为 hook 每次渲染都重新执行一遍,所以获取的是之前的闭包的值。useRef 是解决此类问题的惯用法。 | 
|      4cutpictureboyxx      2022-10-23 13:10:18 +08:00 useEffect(()=>{ const interval = setInterval(()=>{ console.log('timeDate', timeDate) // 一直是 '00:00:00' console.log('timeDateG', timeDateG) // 解决方法 1 }, 2000) return () => clearInterval(interval) }, [timeDate, timeDateG]) | 
|      5joesonw      2022-10-23 13:11:21 +08:00 via iPhone  1 useEffect 也得 watch timeDate | 
|  |      7ragnaroks      2022-10-23 13:26:59 +08:00 idiot: const [timeDate, setTimeDate] = useState('00:00:00') useEffect(()=>{ const interval = setInterval(()=>{ console.log(timeDate) }, 2000) return () => clearInterval(interval) }, [timeDate]) kid: const [timeDate, setTimeDate] = useState('00:00:00') const ref1 = useRef(timeDate) useEffect(()=>{ const interval = setInterval(()=>{ console.log(ref1.current) }, 2000) return () => clearInterval(interval) }, [ref1]) legend: const [timeDate, setTimeDate] = useState('00:00:00') useEffect(()=>{ const interval = setInterval(()=>{ setTimeDate((prev)=>console.log(prev)) }, 2000) return () => clearInterval(interval) }, [setTimeDate]) | 
|  |      8ragnaroks      2022-10-23 13:28:04 +08:00 setTimeDate((prev)=>console.log(prev)) 修正为: setTimeDate(function(prev){ console.log(prev); return prev; }) | 
|      9TWorldIsNButThis      2022-10-23 13:31:31 +08:00 @estk 这是 anti-pattern 因为每次重新渲染都清除了上一个 interval 创建了一个新的 interval | 
|      10TWorldIsNButThis      2022-10-23 13:37:37 +08:00 @estk  这个问题的本质是闭包捕获了一个变量,但是由于每次重新渲染都生成了新的变量,因此导致捕获的变量其实只有这个闭包在使用它 正确的做法就是让闭包捕获一个不变的引用,然后每次值变化同步修改引用的值,也就是 useRef | 
|  |      11darkengine      2022-10-23 15:59:20 +08:00 | 
|      12dcsuibian      2022-10-23 16:14:05 +08:00 react hooks 闭包陷阱 | 
|  |      14hzxxx      2022-10-23 23:55:24 +08:00 我觉得这逻辑不太对,你认同的解决方式,它只是获取到最新的 timeDate ,但是 setInterval 是最后一次更新 timeDate 之后的 2s 执行,但是你代码表达的就是不管 timeDate 更新多少次,我只要组件挂载了,就要在挂载的 setInterval2s 后获取到最新的 timeDate 。 | 
|  |      15linkopeneyes      2022-10-24 15:29:43 +08:00 react 实在太累了,如果有的选我宁愿 solidjs | 
|      16realJamespond      2023-03-03 09:34:14 +08:00 回调里 ``` setTimeDate(prev=>prev) prev 就是最新值 ``` |