A Look at React Hooks: useRef vs useState
Let's learn about the differences between useRef vs useState and uncontrolled vs controlled components!
When learning about React Hooks, you will probably come across useRef
and useState
. These two hooks are often used in form handling. In React, there are typically 2 ways to implement forms: Uncontrolled vs Controlled components.
Welcome to another article of A Look at React Hooks, a beginner-friendly series on React Hooks. In this article, let's learn about the differences between uncontrolled and controlled components, and how to implement them with the useRef
and useState
Hooks.
If you haven't read already, check out my Introduction to useRef and my Introduction to useState articles as a refresher.
Controlled Components
Let's take a look at a simple form example.
export default function App() {
const [name, setName] = useState("");
const onInputSubmit=(e)=>{
e.preventDefault();
alert(`The name you entered was: ${name}`)
}
return (
<div className="App">
<form onSubmit={onInputSubmit}>
<label>
Enter your name:
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
/>
</label>
<button type="submit">Enter</button>
</form>
</div>
)
In this form, we can see that React's useState
Hook is used to track and handle changes to the input value. As the onChange
handler updates the state, name
, constantly whenever the user makes changes to the input, the input component is controlled. Its state is the single source of truth of the input's value.
In summary, Controlled components:
useState
to handle input for a form- Uses
onChange
attribute to manage and update the state's value, making in a single source of truth - Usually the best way of form handling, because we can control individual form elements
- For multiple inputs, we can use the form to capture the form data in one object:
[form, setForm] = useState({ firstName:"", lastName:"" })
- Keeping values in state tends to yield better outcomes in managing form data
Uncontrolled Components
Unlike controlled components, uncontrolled components are where form elements are directly accessed and handled by the DOM itself. React does not handle the input's value and has no way of controlling/updating its value.
In order to access the element via the DOM, we use the useRef
Hook. Let's take a look at this example.
export default function App() {
const inputElement = useRef();
const onInputSubmit=(e)=>{
e.preventDefault();
alert(`The name you entered was: ${inputElement.current.value}`)
}
return (
<div className="App">
<form onSubmit={onInputSubmit}>
<label>
Enter your name:
<input
type="text"
ref={inputElement}
/>
</label>
<button type="submit">Enter</button>
</form>
</div>
)
The notable differences between the uncontrolled example and the controlled one should be obvious when we look at the code. There is no state management by React. We simply add a ref
attribute in the input element to get access to its value, inputElement.current.value
.
In summary, Uncontrolled components:
useRef
to access the form element directly- Use the
ref
attribute to get the form value - Useful for when you want to grab an individual DOM element quickly, or when there's an input deeply nested in a form, or it is an input where it doesn't have to be submitted, just a temporary value
- Good to use for when you don't want to trigger a re-render, because for
useState
, if there are state changes, the component re-renders
Conclusion
In this article, we learned about controlled and uncontrolled components, how they are different and implemented via the useState
or the useRef
Hooks.
I hope this article has helped you understand these concepts better. If it has, please give a like and share this article! Thanks for reading! Cheers!