草庐IT

javascript - react Hook : accessing up-to-date state from within a callback

coder 2025-01-09 原文

编辑(2020 年 6 月 22 日):由于这个问题引起了一些新的兴趣,我意识到可能存在一些困惑。所以我想强调:问题中的例子只是一个玩具例子。它不能反射(reflect)问题。引发这个问题的问题是使用第三方库(对其控制有限),该库将回调作为函数的参数。为该回调提供最新状态的正确方法是什么。在 React 类中,这将通过使用 this 来完成。在 React hooks 中,由于状态被封装在 React.useState() 函数中的方式,如果回调获取状态通过 React.useState() ,它将是陈旧的(设置回调时的值)。但如果它设置状态,它将可以通过传递的参数访问最新状态。这意味着我们可以通过将状态设置为与原来相同的状态,从而使用 React 钩子(Hook)在此类回调中获得最新状态。这可行,但违反直觉。

-- 原问题在下面继续--

我正在使用 React 钩子(Hook)并尝试从回调中读取状态。每次回调访问它时,它都会恢复为默认值。

使用以下代码。无论我点击多少次,控制台都会继续打印 Count is: 0

function Card(title) {
  const [count, setCount] = React.useState(0)
  const [callbackSetup, setCallbackSetup] = React.useState(false)
  
  function setupConsoleCallback(callback) {
    console.log("Setting up callback")
    setInterval(callback, 3000)
  }

  function clickHandler() {
    setCount(count+1);
    if (!callbackSetup) {
      setupConsoleCallback(() => {console.log(`Count is: ${count}`)})
      setCallbackSetup(true)
    }
  }
  
  
  return (<div>
      Active count {count} <br/>
      <button onClick={clickHandler}>Increment</button>
    </div>);
  
}

const el = document.querySelector("#root");
ReactDOM.render(<Card title='Example Component' />, el);

您可以找到此代码 here

我在回调中设置状态没有问题,只是在访问最新状态时遇到了问题。

如果让我猜一猜,我认为任何状态的改变都会创建 Card 函数的一个新实例。并且回调指的是旧回调。基于 https://reactjs.org/docs/hooks-reference.html#functional-updates 处的文档,我有一个想法,采取在回调中调用 setState 的方法,并将一个函数传递给 setState,看看我是否可以从 setState 中访问当前状态。替换

setupConsoleCallback(() => {console.log(`Count is: ${count}`)})

setupConsoleCallback(() => {setCount(prevCount => {console.log(`Count is: ${prevCount}`); return prevCount})})

您可以找到此代码 here

这种方法也没有奏效。 编辑:实际上第二种方法确实有效。我只是在我的回调中有一个错字。这是正确的做法。我需要调用 setState 来访问之前的状态。尽管我无意设置状态。

我觉得我对 React 类采用了类似的方法,但是。为了代码的一致性,我需要坚持使用 React Effects。

如何从回调中访问最新的状态信息?

最佳答案

对于您的场景(您不能继续创建新的回调并将它们传递给您的第 3 方库),您可以使用 useRef 使可变对象保持当前状态。像这样:

function Card(title) {
  const [count, setCount] = React.useState(0)
  const [callbackSetup, setCallbackSetup] = React.useState(false)
  const stateRef = useRef();

  // make stateRef always have the current count
  // your "fixed" callbacks can refer to this object whenever
  // they need the current value.  Note: the callbacks will not
  // be reactive - they will not re-run the instant state changes,
  // but they *will* see the current value whenever they do run
  stateRef.current = count;

  function setupConsoleCallback(callback) {
    console.log("Setting up callback")
    setInterval(callback, 3000)
  }

  function clickHandler() {
    setCount(count+1);
    if (!callbackSetup) {
      setupConsoleCallback(() => {console.log(`Count is: ${stateRef.current}`)})
      setCallbackSetup(true)
    }
  }


  return (<div>
      Active count {count} <br/>
      <button onClick={clickHandler}>Increment</button>
    </div>);

}

您的回调可以引用可变对象来“读取”当前状态。它将在其闭包中捕获可变对象,并且每次渲染可变对象时都将使用当前状态值进行更新。

关于javascript - react Hook : accessing up-to-date state from within a callback,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57847594/

有关javascript - react Hook : accessing up-to-date state from within a callback的更多相关文章

随机推荐