React useRef : DOM Manipulation
Syntax
import { useRef } from 'react';
const ref = useRef(initialValue);
With the use of useRef, we can achieve the same result as?document.getElementById('myInput'), but in a more React-friendly way.
const myRef = useRef(null); // { current: null }
<input ref={myRef} />
By declaring?const myRef = useRef(null);, we create a useRef object with an initial value of?null.
When we use?<input ref={myRef} />?in our React component, React creates a DOM node for the?<input>?element. React then assigns a reference to this node to?myRef.current.
Since?myRef.current?now holds a reference to the actual DOM node of the?<input>?element, you can perform operations or access properties and methods of the DOM node through the?myRef.current?object. This allows you to manipulate the DOM directly, if necessary, within a React component.
const inputRef = useRef(null);
function handleClick() {
inputRef.current.focus();
console.log("inputRef.current", inputRef.current);
}
return (
<>
<input ref={inputRef} placeholder="Write your name" />
<button onClick={handleClick}>Focus the input</button>
</>
);
When you inspect the console, you'll get
inputRef.current <input placeholder="Write your name" />
Use cases:
Focus, scroll position, or measuring DOM elements.
领英推荐
Usually, those use cases are used because directly manipulating the DOM can often lead to unexpected behaviors and conflicts with React's internal operations.
As stated in the React documentation, "If you try to modify the DOM manually, you can risk conflicting with the changes React is making."
The code below is from the React Documentation.
import { useState, useRef } from 'react';
export default function Counter() {
const [show, setShow] = useState(true);
const ref = useRef(null);
return (
<div>
<button
onClick={() => {
setShow(!show);
}}>
Toggle with setState
</button>
<button
onClick={() => {
ref.current.remove();
}}>
Remove from the DOM
</button>
{show && <p ref={ref}>Hello world</p>}
</div>
);
}
"After you’ve manually removed the DOM element, trying to use setState to show it again will lead to a crash. This is because you’ve changed the DOM, and React doesn’t know how to continue managing it correctly."
In general, when working with DOM elements in React, it is recommended to use?useRef?instead of?document.getElementById.
DOM manipulation must occur at the appropriate time because of the React component lifecycle.
When the component renders, the ref value may not have been updated yet. If you try to read or modify the ref value directly during rendering, it might lead to incorrect or stale data. ("Do not write or read ref.current during rendering.")
To avoid the conflict, we use?useEffect.
import React, { useRef, useEffect } from 'react';
function MyComponent() {
const myRef = useRef(null);
useEffect(() => {
if (myRef.current) {
myRef.current.focus();
}
}, []);
return <input ref={myRef} />;
}
By using useEffect appropriately, you can ensure that your DOM manipulations align with React's rendering and reconciliation process, which helps maintain the integrity of the virtual DOM and avoids inconsistencies or unexpected behavior.
While useEffect can address the issues related to React's virtual DOM, its main role is to handle side effects (e.g., operations like DOM manipulation, API calls, event listeners) rather than directly affecting how React manages the virtual DOM.
According to the document, it is possible to modify the DOM, but it is advisable to use it with caution and consider using DOM manipulation primarily for non-destructive actions.