When you want a component to "remember" some information, but you don't want that information to trigger new renders, you can use a ref. Refs can be thought of as an "escape hatch" from React's unidirectional data flow.
To create a ref, you can use the useRef Hook:
import { useRef } from 'react';
const MyComponent = () => {
const ref = useRef(0);
// ...
return (
// ...
);
}
useRef takes an argument as the initial value and returns an object with a current property. This current property represents the value held by the ref, and you can read and modify this value.
The difference between refs and state is that changing a ref does not trigger a re-render of the component. This makes refs useful for storing values that are not used during rendering but need to be accessed by event handlers.
Here's a simple counter example:
import { useRef } from 'react';
const Counter = () => {
const countRef = useRef(0);
const handleClick = () => {
countRef.current++;
console.log(`Clicked ${countRef.current} times`);
};
console.log('Component rendered');
return (
<button onClick={handleClick}>
Click me
</button>
);
};
In this example, countRef is defined as a ref with an initial value of 0. Every time the handleClick function is called, the countRef.current value is incremented and logged to the console. However, note that the component is not re-rendered when countRef is modified. You will see that the "Component rendered" message is logged only once in the console output.
Refs are useful when working with external systems or browser APIs in React components. However, it's important to avoid overusing refs. Relying on refs instead of changing state can reduce the readability and predictability of your code.
When using refs, avoid reading or writing ref.current during rendering. This can make the behavior of your component hard to predict.
Refs are not subject to the limitations of state in React. For example, state acts like a snapshot for each render and doesn't update synchronously. However, when you modify the current value of a ref, that change happens immediately.
You don't need to worry about avoiding mutation when working with refs. As long as you're mutating an object that is not used for rendering, React doesn't care what you do with the ref or its contents.
By using refs correctly, you can achieve more advanced and flexible behaviors in your React components. However, remember to use refs only when necessary and with caution.