useEffect.dev
← Back to lessons

Lesson 6. Get the current state when dealing with async code 3. Exercise & next steps

We just saw how to use a ref to get the current state. It’s nice but creating the state, then the ref, then calling useEffect to update the ref each time the state is, can seem repetitive when you do it for the third time.

Would you be able to write a custom hook to makes things more elegant? We would use it like this:

const [original, setOriginal, originalRef] = useStateRef('Original value')

Complete the following code by writing the custom hook useStateRef, and use it in the App component:

Result
Click here to see the solution!
const useStateRef = (initialValue) => {
const [value, setValue] = useState(initialValue)
const valueRef = useRef(value)
useEffect(() => {
valueRef.current = value
}, [value])
return [value, setValue, valueRef]
}
const App = () => {
const [original, setOriginal, originalRef] = useStateRef('Original value')
const [copy, setCopy] = useState('')
const handleClick = () => {
setTimeout(() => {
setCopy(originalRef.current)
}, 2000)
}
return (
<>
<input
type="text"
value={original}
onChange={(e) => setOriginal(e.target.value)}
/>
<button onClick={handleClick}>Copy in 2 seconds</button>
<p>Copy: {copy}</p>
</>
)
}
render(App)

Next steps

We’ve seen a very common problem caused by hooks; let’s see a second one: infinite loops caused by faulty use of useEffect.