
Understanding the useState Hook
It is a built-in React hook that allows you to add a state to functional components. It takes an initial value as an argument and returns an array with two elements: the current state and a function to update that state. And it triggers a re-render component when its value changes. It can cause performance issue if using it in wrong way. UseState is an asynchronous hook and it doesn’t change the state immediately, it has to wait for the component to re-render. This is also important point that need to remember.
Like below example, our component will be looped in re-rendering
function MyComponent() {
const [darkMode, setDarkMode] = useState(true);
setDarkMode(false);
return <div class={darkMode ? "dark-mode": "light-mode" }>This is my component</div>;
}
Therefore, we always wrap it in callback function and execute when need. Or use with useEffect hook (we’re not going deeply it in this article).
function MyComponent() {
const [darkMode, setDarkMode] = useState(true);
function changeMode = () => {
setDarkMode(false);
};
return <div>
<div class={darkMode ? "dark-mode": "light-mode" }>This is my component</div>;
<input type="button" text="Switch Mode" onClick="changeMode" />
</div>;
}
React DevTools is especially helpful here to visually highlight updates when components render. In the last recording, you can see the flashing border around the component that notifies you of another component rendering cycle.
Understanding the useRef Hook
It is another built-in React hook that allows you to store a mutable value that persists between renders. useRef is a synchronous hook that updates the state immediately and persists its value through the component’s lifecycle, but it doesn’t trigger a re-render.
function MyComponent() {
const myRef = useRef(null);
function handleClick() {
myRef.current.style.color = 'red';
}
return (
<div>
<p ref={myRef}>This text can be changed</p>
<button onClick={handleClick}>Change text color</button>
</div>
);
}
Comparing between two hooks
| UseState | UseRef | |
| Purpose | To manage the state in a component. | To create a mutable reference to a DOM node or a value. |
| Type of value | Can store any serializable JavaScript value, including objects and arrays. | Can store any JavaScript value. |
| Returns | A stateful value and a function to update it. | A mutable object with a .current property. |
| Initial value | Passed as an argument to the useState() function. | Passed as an argument to the useRef() function. |
| Re-renders | When the state value changes. | Never triggers a re-rendernode or a value that needs to persist across renders. |
| Updating the value | Call the update function returned by useState(). | Update the .current property directly. |
| Accessing the value | Use the state value returned by useState(). | Access the value using the .current property of the mutable object returned by useRef(). |
Usecases when use useRef instead of useState
A rule of thumb is to use useState when you need to re-render the component when the state changes and useRef when you don’t need to re-render the component when the state changes.
Here are some examples of when to use useRef instead of useState:
- When you need to store a reference to a DOM.
- When you need to store a value that does not trigger a re-render when it is updated.
- When you need to store a value that is not used in the render method.
- When you need to store a value that persists for the lifetime of the component (updating value will be reflected immediately without waiting on the completed re-rendering).
References
https://dev.to/trinityyi/when-to-use-useref-instead-of-usestate-3h4o
https://dzone.com/articles/usestate-vs-useref-understand-the-technical-differ