paljakka
全ての投稿に戻る

How to use React useRef

公開日 2024-09-29

What is useRef

useRef is React hook that returns mutable ref object with property current. useRef allows you to access DOM which is useful in alot of cases where you need access to elements. When i was starting with the React, i was thinking what is the difference between the vanilla querySelector and React ref.

So useRef is very handy for accessing DOM elements, but what it is really powerful for is that you get access to persisted state of value through the component’s lifecycle.

Most of examples how to manage state with React are examples using useState. Which is obviously fine in alot of cases, but it has little caveat. Changing the state with useState is re-rendering your application everytime it changes, this is not always necessary.

Why not document.querySelector instead ?

useRef has similarities with the vanilla Javascript querySelector but technically it is completely different thing. Unlike ref, querySelector returns the first element within the document that matches the specified css selector, or group of selectors. With the useRef we have direct access to element.

Problem using querySelector with React is that React replaces existing elements in dom on state change and although elements look the same and even have same properties, they are not the exactly the same element object. Also if you have SSR setup to your React app, document and window for example wont work out of the box with SSR.

Examples

So these are few simplified versions i've seen in real customer projects and they helped me to understand the useRef better.

  1. usecase with simple login form So first example is typical simple login form, many times i've seen this kind of case done with the useState. Here we use ref to access input value. Benefit in this kind of approach is slight performance improvement compared to useState. You can use this same way as useState to display validation errors.
export default function LoginForm({ onSubmit }) { const loginNameRef = useRef(); const passwordRef = useRef(); function handleLogin(evt) { evt.preventDefault(); onSubmit({ loginName: loginNameRef.current.value, password: passwordRef.current.value, }); } return ( <form onSubmit={handleLogin}> <label htmlFor="loginName">Login name</label> <input ref={loginNameRef} type="text" id="loginName" /> <label htmlFor="password">Password</label> <input ref={passwordRef} type="password" id="password" /> <button type="submit">Login</button> </form> ); }
  1. usecase with Intersectional Observer In this example we use useRef to select element we want to observe and use also useState to manipulate dom. So this example we want to select LoginForms wrapper and when this wrapper gets into viewport paragraph text changes. This kind of solution is useful when you need to do something when element is getting into viewport, for example triggering animation.
export default function App() { const containerRef = useRef(null); const [isVisible, setIsVisible] = useState(false); const onVisible = useCallback((entries) => { const [entry] = entries; setIsVisible(entry.isIntersecting); }, []); useEffect(() => { const observer = new IntersectionObserver(onVisible, { threshold: 0.6, }); const element = containerRef.current; element && observer.observe(element); return () => { element && observer.unobserve(element); }; }, [onVisible]); function onLogin(loginInfo) { console.log(loginInfo); } return ( <div className="app"> <div className="head">{isVisible ? 'visible' : 'not visible'}</div> <div className="section" /> <div className="loginContainer" ref={containerRef}> <LoginForm onSubmit={onLogin} /> </div> </div> ); }

Conclusion

useRef is synchronous hook that is updating state immediately and persisting the state through the component’s lifecycle without re-render. However, nothing is great when overused and sometimes you can find use with combination of useState and useRef for example.