访问 useRef 中包含的函数的 React 状态不会更新

Access React state of function enclosed inside useRef doesn't update

提问人:jsindos 提问时间:7/9/2022 更新时间:2/9/2023 访问量:595

问:

我正在尝试访问包含在 中的函数内的 React 状态。但是,即使将帮助程序函数绑定到访问状态,状态也不会在函数内部更新。useRefAppuseRef

getCount outside 0
// after clicking, getCount inside is still 0, even though count now equals 1
getCount outside 1
getCount inside 0
import React, { useState, useRef } from 'react'
import ReactDOM from 'react-dom'

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

  const getCount = function () {
    return count
  }.bind(App)

  console.log('getCount outside', getCount())

  const onClick = useRef(() => {
    console.log('getCount inside', getCount())
  })

  return (
    <>
      <div onClick={() => setCount(count + 1)}>
        increment count
      </div>
      <div onClick={onClick.current}> 
        {count}
      </div>
    </>
  )
}

const wrapper = document.getElementById('root')
ReactDOM.render(<App />, wrapper)
javascript reactjs 这个

评论

2赞 bogdanoff 7/9/2022
更改为 .setCount(count + 1)setCount((count) => count + 1)

答:

1赞 CertainPerformance 7/9/2022 #1

只有在装入组件时才会考虑传递给的参数。只有在这个时候,才会将值分配给 ref;当组件重新呈现时,它不会更新。useRef

当组件挂载时,ref 函数关闭的变量是初始状态值,即 0。无论组件重新渲染多少次,ref 的函数(如果不重新赋值)仍将关闭该原始状态值。count

如果希望 ref 的函数生成最新值,请在每次重新渲染时重新分配该值。

// assign nothing notable on mount, just create a ref
const onClickRef = useRef();
// on mount and on re-render, assign a function
// with an up-to-date reference to the state variable
onClickRef.current = () => {
  console.log(count);
};

不过,在 React 中,通常最好将状态本身传递下来并使用它,而不是 ref - refs 通常用于使用 React 提供的更强大的工具无法完成的事情。

评论

0赞 jsindos 7/9/2022
太好了,谢谢你的回答。我意识到我可以在我的 ref 函数中更新状态,然后将此状态更新作为 ref 之外的效果进行响应。对于任何对用例感到好奇的人,我在将常规函数传递给 React Native 内部时会得到。Invariant Violation: Changing onViewableItemsChanged on the fly is not supportedonViewableItemsChangedScrollView
1赞 Florin Dobre 2/9/2023 #2

在 setter 中使用带有 previousValue 的回调可以解决这个问题:

const onClick = useRef(() => {
  console.log(count); <----- always 0 (initial state)
  
  setCount((previousValue)=> {
    console.log(previousValue); <---- correct current value each time
    return previousValue+1;
  }
})

来源:想法来自@bogdanoff对问题的第一条评论。点赞。