I'm trying to access React state inside a function enclosed inside of useRef
. However, even with a helper function bound to App
to access the state, the state never updates inside of the useRef
function.
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)
CodePudding user response:
The argument passed to useRef
is only considered when the component mounts. Only at that time is the value assigned to the ref; it won't update when the component re-renders.
When the component mounts, the count
variable that the ref's function closes over is the initial state value, which is 0. No matter how many times the component re-renders, the ref's function, if not reassigned, will still close over that original state value.
If you want the ref's function to result in an up-to-date value, assign it anew each time there's a re-render.
// 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);
};
Though, in React, usually it'd be better to pass the state itself down and use it, rather than a ref - refs are generally for things that you can't accomplish using the more functional tools provided by React.