Education
Developer Advocate
Last updated on Sep 15, 2023
Last updated on Aug 24, 2023
As a developer, you've probably encountered the terms "controlled" and "uncontrolled components" in the React ecosystem. These concepts are fundamental to understanding how data flows and is managed within a React application. But, let's be honest, they can also be a bit tricky to wrap your head around, especially when it comes to uncontrolled components.
Uncontrolled components in React are those where the form data is handled by the DOM itself, not by the state within your component. In essence, they're a bit like traditional HTML form inputs. When you need to get your hands on the value, you reach out directly to the DOM to fetch it.
Here's a simple example of an uncontrolled component:
1 import React from 'react'; 2 3 function App() { 4 let inputRef = React.createRef(); 5 6 const handleSubmit = event => { 7 alert('A name was submitted: ' + inputRef.current.value); 8 event.preventDefault(); 9 }; 10 11 return ( 12 <form onSubmit={handleSubmit}> 13 <label> 14 Name: 15 <input type="text" ref={inputRef} /> 16 </label> 17 <input type="submit" value="Submit" /> 18 </form> 19 ); 20 } 21 22 export default App; 23
In the above code, we're using React.createRef() to create a ref, which we then attach to our input element. When the form is submitted, we can access the current value of the input directly through this ref.
The key takeaway here is that the DOM is the source of truth for the input value, not the React component's state. This is the defining characteristic of uncontrolled components.
Now, you might be wondering, "Why would I want to use uncontrolled components? Aren't controlled components the React way of doing things?" Well, yes and no. While controlled components do offer a high degree of control and are often the go-to choice, uncontrolled components have their place too. But more on that later. For now, let's delve a bit deeper into how uncontrolled components work in functional components.
In functional components, uncontrolled components work a bit differently than in class components. Instead of using React.createRef(), we use the useRef() hook. This hook creates a mutable object with a current property, which we can then use to store our input reference.
Here's an example of an uncontrolled component in a functional component:
1 import React, { useRef } from 'react'; 2 3 function App() { 4 const inputRef = useRef(); 5 6 const handleSubmit = event => { 7 alert('A name was submitted: ' + inputRef.current.value); 8 event.preventDefault(); 9 }; 10 11 return ( 12 <form onSubmit={handleSubmit}> 13 <label> 14 Name: 15 <input type="text" ref={inputRef} /> 16 </label> 17 <input type="submit" value="Submit" /> 18 </form> 19 ); 20 } 21 22 export default App; 23
In this code, we're using useRef() to create a ref, which we then attach to our input element. When the form is submitted, we can access the current value of the input directly through this ref, just like we did in the class component example.
The key thing to remember here is that, even though we're using a hook (which is usually associated with state and effects), the useRef() hook doesn't cause a re-render when the ref changes. This makes it perfect for cases like this, where we want to store a mutable value that doesn't affect the component's output.
So, there you have it: uncontrolled components in functional components. They're a bit different, but once you get the hang of them, they're just as easy to use as their class-based counterparts.
Now that we've got a handle on what uncontrolled components are, let's take a moment to contrast them with controlled components. Understanding the differences between these two types of components is crucial for making informed decisions about which one to use in a given situation.
Controlled components in React are those where the state of the form data is managed within the React component. Every state mutation has an associated handler function, making it straightforward to modify or validate user input.
Here's an example of a controlled component:
1 import React, { useState } from 'react'; 2 3 function App() { 4 const [name, setName] = useState(''); 5 6 const handleChange = event => { 7 setName(event.target.value); 8 }; 9 10 const handleSubmit = event => { 11 alert('A name was submitted: ' + name); 12 event.preventDefault(); 13 }; 14 15 return ( 16 <form onSubmit={handleSubmit}> 17 <label> 18 Name: 19 <input type="text" value={name} onChange={handleChange} /> 20 </label> 21 <input type="submit" value="Submit" /> 22 </form> 23 ); 24 } 25 26 export default App; 27
In this code, we're using the useState() hook to manage the state of the name input. When the input changes, we update the state with the new value. When the form is submitted, we can access the current value directly from the state.
The key differences between controlled and uncontrolled components can be boiled down to the following points:
Understanding these differences will help you make more informed decisions about which type of component to use in your React applications.
At this point, you might be wondering why you'd ever want to use uncontrolled components. After all, controlled components give you more control (hence the name), right? While that's true, there are several reasons why you might want to use uncontrolled components in certain situations.
Remember, React gives you the flexibility to choose between controlled and uncontrolled components based on what suits your use case best. It's all about picking the right tool for the job!
Now, let's take a moment to talk about a tool that can make your job as a React developer even easier. Meet WiseGPT, a promptless Generative AI for React developers. It writes code in your style, without context limit, and provides API integration by accepting Postman collection. It even supports extending UI in the VSCode itself. Imagine having an AI pair programmer that understands your coding style and helps you write better code, faster. Sounds pretty cool, right? But I digress. Let's get back to our exploration of controlled and uncontrolled components.
Now that we've covered uncontrolled components, let's switch gears and talk about how to write a controlled component in React. As we've learned, controlled components are all about managing form data within the component's state. So, let's see this in action:
1 import React, { useState } from 'react'; 2 3 function App() { 4 const [name, setName] = useState(''); 5 6 const handleChange = event => { 7 setName(event.target.value); 8 }; 9 10 const handleSubmit = event => { 11 alert('A name was submitted: ' + name); 12 event.preventDefault(); 13 }; 14 15 return ( 16 <form onSubmit={handleSubmit}> 17 <label> 18 Name: 19 <input type="text" value={name} onChange={handleChange} /> 20 </label> 21 <input type="submit" value="Submit" /> 22 </form> 23 ); 24 } 25 26 export default App; 27
In the above code, we're using the useState() hook to manage the state of the name input. When the input changes, we update the state with the new value. When the form is submitted, we can access the current value directly from the state.
This is a simple example, but it illustrates the key point: In a controlled component, the React state is the single source of truth for the form data. This gives us a lot of control (again, hence the name) over the form data and how it's handled.
Writing a controlled component might seem a bit more complex than writing an uncontrolled component, but the benefits often outweigh the extra code. With a controlled component, you have the power to manipulate and validate user input on the fly, making it a powerful tool in your React toolkit.
As we delve deeper into the world of React, it's important to understand the relationship between controlled/uncontrolled components and stateless/stateful components. While these concepts are distinct, they intersect in interesting ways that can influence how we structure our applications.
Stateless components, also known as functional components, do not have their own state. They receive data through props and render it. On the other hand, stateful components, also known as class components, maintain their own state and have lifecycle methods.
Now, let's bring components into the picture. A controlled component can be either stateful or stateless. If it's stateful, it uses the class component's state to manage form data. If it's stateless, it uses hooks (like useState()) to manage form data.
On the other hand, an uncontrolled component can also be either stateful or stateless. Regardless of its type, it does not use the component's state to manage form data. Instead, it relies on the DOM to handle this.
So, in a nutshell, the terms "controlled/uncontrolled" and "stateful/stateless" refer to different aspects of a component. The former is about where the form data is stored and managed, while the latter is about whether the component has its own state and lifecycle methods.
Understanding these nuances can help you make more informed decisions when designing and building your React applications. It's all part of the journey to becoming a more effective and efficient React developer.
As we continue to explore the intricacies of React and its components, it's worth mentioning a tool that can significantly streamline your React development process. Enter WiseGPT, an AI-powered assistant that's designed to help you write React code more efficiently.
WiseGPT is a generative AI that writes code in your style, without context limit. It integrates seamlessly with your development environment, providing API integration by accepting Postman collection and even extending UI in the VSCode itself.
Imagine having an AI pair programmer that understands your coding style and helps you write better code, faster. It's like having a seasoned React developer by your side, ready to assist you at any time. With WiseGPT, you can focus more on the logic and design of your application, and less on the nitty-gritty details of coding.
But enough about tools. Let's get back to our exploration of controlled and uncontrolled components in React.
We've come a long way in our exploration of controlled and uncontrolled components in React. We've seen that both types of components have their own strengths and use cases, and the choice between them often depends on the specific requirements of your application.
Controlled components offer a high degree of control over form data, making them a great choice when you need to validate or manipulate user input on the fly. On the other hand, uncontrolled components can be more performant and simpler to write, making them a good fit for large forms or when you only need the data when the form is submitted.
In the end, the decision between controlled and uncontrolled components is not a matter of right or wrong, but rather a matter of choosing the right tool for the job. React gives us the flexibility to choose the approach that best suits our needs, and that's one of the things that makes it such a powerful library for building user interfaces.
So, the next time you're working on a React form, take a moment to consider whether a controlled or uncontrolled component would be the best fit. And remember, whether you're a seasoned React developer or just starting out, there's always more to learn and discover in the ever-evolving world of web development. Happy coding!
Tired of manually designing screens, coding on weekends, and technical debt? Let DhiWise handle it for you!
You can build an e-commerce store, healthcare app, portfolio, blogging website, social media or admin panel right away. Use our library of 40+ pre-built free templates to create your first application using DhiWise.