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)
Advertisement
Answer
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.