React: Controlled vs Uncontrolled Components
Let's talk about controlled vs uncontrolled React components, with some examples. We’ll discuss their advantages and disadvantages, and finally, we’ll look at the Formik library.
Let's talk about React controlled vs uncontrolled components. We’ll discuss their advantages and disadvantages, investigate some examples along the way, and finally, look at Formik, a form library available in the React ecosystem.
Without further ado, let’s get started!
Prerequisites
To follow along with this article, I would highly recommend reading these articles for some background:
What is a Controlled Component?
Controlled components are components whose value is directed/driven by React’s state. By state, we mean the state we store inside a React component, i.e., inside this.state or with useState.
This means that these components will receive the latest changes.
For any controlled component, we pass our state variable inside the value prop of the component. The function that changes this state variable of the component is passed in the onChange prop of the controlled component.
Here is an example that demonstrates a controlled component:

Let’s explain:
Appis a simple function-based React component.Its
rendermethod consists of aformwith aninputelement and astrongelement that displays the value of the state variable of the component.We pass the state variable
inputValueas avalueprop to the input element.Similarly, we pass the
handleOnChangefunction to theonChangeprop of the input component.Now, whatever you type inside the input element will set the value of the
inputValuestate viahandleOnChange, and then the same will be displayed in theinputelement.To show that the state variable
inputValueis changing, we display it inside thestrongelement.
The controlled component’s value prop does not always need to be a component’s internal state. It can be a prop of the parent component, or it can come from the Redux store. This is similar to the onChange prop.

In a similar manner, we can use react-redux to get the state and the handleOnChange function from the Redux store to have similar functionality to what we had when we were using useState.
The same context can be applied to the checkbox, radio, text area, and select DOM elements so that they can act as controlled elements.
Here are some of the advantages of using controlled components:
The UI and the data are in sync
Form data can be passed between different components
The event handler and the value prop can be from the parent or a redux store
The React component acts as a source of truth for this component
Some disadvantages of controlled components:
They render at each input change
A controlled component can be a bad choice when large changes are required to be made to the component
What is a React Uncontrolled Component?
As the name suggests, the value of uncontrolled components is not driven by the React component’s state variable. It's completely controlled by the DOM.
Uncontrolled components are generally used when the use case is simple or the action is not trackable; for example, a user uploading a file using file input.
The basic requirement of any uncontrolled component is to be handled by the DOM. In this case, we cannot pass the state variable inside the form’s input element. Now the question arises — how are we going to set the value inside this input element?
We use React’s useRef for functional components or createRef for class-based components. A useRef is a hook that returns a mutable object with current as its property with value being initialValue that is passed inside the hook.
Here is the syntax of the useRef hook:

A ref object can be used in many ways, e.g., as a state variable that does not re-render the component on change, to access DOM elements, etc.
We can leverage this into our React uncontrolled component to access input elements attributes, i.e., value properties.
Here's a simple example of how you can create an uncontrolled component:

As you can see, this App component consists of form and a bunch of span elements. We use the JSON placeholder API in the component to fetch the post based on id. This is the summary of our component, but let’s understand a bit more about how the App component works internally.
Inside the
formelement, we have a staticselectelement with a couple of options.We are making use of a
refobject here. Thisrefobject is named asselectRefand this is being passed on to theselectelement as arefprop.Here comes the catch— we don’t need to watch for any changes that happen to the
selectelement, nor do we need to make use of a state variable to keep track of the current value that is selected in this element.This begs the question, how do we get the latest value from the
selectelement?Well, we don’t need to. This is an uncontrolled component/element; a component/element that is managed by the DOM.
So, the change in the
valueproperty of the select element is managed by the browser.Now we just need to find a way to capture this value.
refscomes to rescue here. Since we passed ourrefobject into theselectelement as a prop, we can now access the value present inside this element.To get hang of this, you can check out the
handleOnSubmitfunction. This function makes use of theselectRef.current.valueto access the value property of theselectelement. TheselectRefstores all of the values inside thecurrentobject. In this case,selectRef.currentwill store theselectelement itself. To access the value, simply access its.valueproperty.Next, the
handleOnSubmitfunction calls the API. On success, we simply store it in the state variableapiData.
Here are some advantages of uncontrolled components:
No component re-renders
Browser DOM handles the changes to the element
Simple to use
Keeps track of the internal state
And some of the disadvantages of uncontrolled components:
Cannot be used in complicated scenarios where we need to pass the value to different components
It’s not always efficient to use uncontrolled components where we require granular control over the value
Formik
Formik is an open-source library to build forms in React and React Native. It’s the world’s leading library for building forms in React.
Formik is a complete solution that helps you to implement form validation, keep track of visited fields, and handle form submission in an efficiently and robustly. It's based on the concept of a controlled component react.
Now, let’s look at one simple example of how can Formik can be used to build a form along with the form validation.
We are going to use the same uncontrolled component example. First, we’ll convert the example into a controlled component and then, use Formik to make our life easier.

Here are some of the brief points that will get you up to speed on understanding the above component:
The Formik library provides us with some easy-to-use components that help us to build Formik forms in no time.
Formik is a wrapper component that helps to build forms.
It takes in
initialValues, which tells the Formik form about the fields and their initial values.Next, we have the
validationSchemaprop. It can accept a Yup object to define validations inside the form.Finally, we provide our
submitHandlerfunction as a callback that needs to be executed whenever a submission takes place.This is a controlled component. All the values are handled by Formik.
In the above component, we have used
Formik,FieldandErrorMessagecomponents. These are similar to the normal input elements present inside the form element.The
Fieldcomponent, as the name suggests, acts as a wrapper component on top of form input elements.Finally, we have the
ErrorMessagecomponent. This component takes in thenameprop. Thisnameprop will be used by this component to provide an element that displays the error message for that particular field.Now, you might be wondering how these components know which field they should work for. Here comes the
nameandidprops to the rescue. You should provide either of these props to make sure yourFieldandErrorMessagecomponents work properly.We should also make sure that we pass the submitted values to Yup’s
validationsthat we set earlier. For example, for the select field, we pass inname="selectVal"in theFieldandErrorMessagecomponents. In this way, Formik knows how to map these wrapper components to their respective fields.
Summary
Now, you've learned some of the differences of React controlled vs uncontrolled components. Choosing which type of component to use in your project completely depends upon your use case.
If you’re looking for tangible results with a simple use case or trying to use memory-intensive operations, such as document editors, uncontrolled components are the way to go.
If you’re looking for more granular control over the values of form elements, then you should use controlled components.
Become More Productive Writing Your React Apps
Every component you create in React requires tons of repetition. Across every frontend project, there are custom setups and best practices that teams follow. Pieces helps you with any React project by creating a local micro-repository where you can store any code snippets and their relevant metadata on your machine. Additionally, Pieces makes it incredibly easy to share your snippets, create collections to onboard others onto a project, and even integrate your snippets directly in your IDE. Our team of developers is pushing changes every day to build the most effective and efficient micro-repo for you.
Try Pieces now using the personal plan for free and supercharge your React projects!




