How do we know when a React ref.current value has changed?
React docs recommend using callback refs to detect ref
value changes.
Hooks
export function Comp() { const onRefChange = useCallback(node => { if (node === null) { // DOM node referenced by ref has been unmounted } else { // DOM node referenced by ref has changed and exists } }, []); // adjust deps return <h1 ref={onRefChange}>Hey</h1>;}
useCallback
is used to prevent double calling of ref callback with null
and the element.
You can trigger re-renders on change by storing the current DOM node with useState
:
const [domNode, setDomNode] = useState(null);const onRefChange = useCallback(node => { setDomNode(node); // trigger re-render on changes // ...}, []);
Class component
export class FooClass extends React.Component { state = { ref: null, ... }; onRefChange = node => { // same as Hooks example, re-render on changes this.setState({ ref: node }); }; render() { return <h1 ref={this.onRefChange}>Hey</h1>; }}
Note: useRef
doesn't notify of ref
changes. Also no luck with React.createRef()
/ object refs.
Here is a test case, that drops and re-adds a node while triggering onRefChange
callback :
componentDidUpdate
is invoked when the component state or props change, so it will not necessarily be invoked when a ref
changes since it can be mutated as you see fit.
If you want to check if a ref has changed from previous render though, you can keep another ref that you check against the real one.
Example
class App extends React.Component { prevRef = null; ref = React.createRef(); state = { isVisible: true }; componentDidMount() { this.prevRef = this.ref.current; setTimeout(() => { this.setState({ isVisible: false }); }, 1000); } componentDidUpdate() { if (this.prevRef !== this.ref.current) { console.log("ref changed!"); } this.prevRef = this.ref.current; } render() { return this.state.isVisible ? <div ref={this.ref}>Foo</div> : null; }}ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://unpkg.com/react@16/umd/react.development.js"></script><script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script><div id="root"></div>