In React, hooks are a way to use state and other React features without having to generate a class component. One of the most frequently used hook is useState()
, however on occasion useRef()
might be a better and more efficient way to manage state.
A common use case is handling a form input field when the submit button is clicked. For example, lets look at the following code snippet:
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const handleSubmit = (e) => {
e.preventDefault();
console.log(email, password);
};
return (
<form onSubmit={handleSubmit}>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
<button type="submit">Submit</button>
</form>
);
In the above example, we have two input fields, one for the email and one for the password. When the submit button is clicked, the values of the two input fields are logged to the console. The useState()
hook is used to manage the state of the two input fields. Although, this code does what it's supposed to do, it also causes the component to re-render every time the input fields are changed.
This is due to the usage of the useState()
hook, which by definition causes the component to re-render every time the state is changed. This is not a problem in this example, but in a more complex application, this can cause performance issues. To avoid this, we can use the useRef()
hook instead of useState()
.
const email = useRef('');
const password = useRef('');
const handleSubmit = (e) => {
e.preventDefault();
console.log(email.current, password.current);
};
return (
<form onSubmit={handleSubmit}>
<input
type="email"
value={email.current}
onChange={(e) => (email.current = e.target.value)}
/>
<input
type="password"
value={password.current}
onChange={(e) => (password.current = e.target.value)}
/>
<button type="submit">Submit</button>
</form>
);
When to 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 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.
Top comments (8)
Thanks for the post - I had to learn the difference between these a month or two ago to improve a contribution to an open-source project and was happy to read this quick post as a reminder of it. Have a good day!
Cool, thanks a lot for sharing!
thanks
So I gave this a try. It doesnt seem to work?
codesandbox.io/s/cocky-bartik-qlmm...
Because if there are no re-renders, the DOM wont update and I wont see the username and password change as I type?
You can do it like this
Okay, now I understand the point! When I used a counter to observe the component's re-rendering, I realized that using useRef retains the state throughout the entire lifecycle of the component. So, every time it re-renders, it doesn't start with the count of 0 again unlike useState. Instead, it holds the previous value and continues counting where it should be. Correct me If I'm wrong!
I didn't quite understand what you said here. So how can useState initialize from 0 every time? Doesn't useState preserve its state value throughout its lifecycle?
Very useful, thanks!