Controlled vs Uncontrolled component in React

In ReactJS, there are controlled components in which some of the values of that component can be changed by themselves, and in an uncontrolled component, the values of that component can not be changed by themselves.

Below is the topic that we will cover in this article,

  • Controlled component
  • Uncontrolled component
  • Stateless and Stateful component

Controlled component in ResctJS

  • Create a react app.
npx create-react-app my-app
cd my-app
npm start

Note: Please read this article to know more about creating a new react project.

  • Declare an input field in the app.js file which is inside the src folder of the project folder
import React, { useState, useEffect } from "react";
const App = () => {

  return (
    <div className="flex justify-center my-16">
      <div className="form-control items-center lg:items-start">
        <input type="text" placeholder="Text" className="input input-bordered " />
      </div>
    </div>
  );
}

export default App

  • Declare an onChange() event handler and a state variable to store the written values in the state hook
import React, { useState, useEffect } from "react";
const App = () => {
  const [inputValue, setInputValue] = useState('')
  return (
    <div className="flex justify-center my-16">
      <div className="form-control items-center lg:items-start">
        <input onChange={e => setInputValue(e.target.value)} type="text" placeholder="Text" className="input input-bordered " />
      </div>
    </div>
  );
}

export default App

Here, we have declared a state to store the values of the input field. And also declared an onChange() event handler to that input field to store the data in that variable.

  • Add a value attribute to that input field and pass the inputValue variable as a value into that.
import React, { useState, useEffect } from "react";
const App = () => {
  const [inputValue, setInputValue] = useState('')
  return (
    <div className="flex justify-center my-16">
      <div className="form-control items-center lg:items-start">
        <input value={inputValue} onChange={e => setInputValue(e.target.value)} type="text" placeholder="Text" className="input input-bordered " />
      </div>
    </div>
  );
}

export default App

Now, what happened now? If we take a closer look into this, with each key change the state will be updated and as the state is updated, the value of the input field will also update. As we are controlling the value depending on our state in this very component, hence this can be a controlled component.

Uncontrolled component in ReactJS

An uncontrolled component is a component where input values will be rendered by the browser DOM’s default behavior. It doesn’t have to do anything with the state.

  • Create an input field
import React, { useState, useEffect } from "react";
const App = () => {

  return (
    <div className="flex justify-center my-16">
      <div className="form-control items-center lg:items-start">
        <input  type="text" placeholder="Text" className="input input-bordered " />
      </div>
    </div>
  );
}

export default App

  • Declare a reference value in the App function to get the input values with DOM’s default behavior
  const textRef = useRef(null);
import React, { useState, useEffect } from "react";
import { useRef } from "react";
const App = () => {
  // const [inputValue, setInputValue] = useState('')

  const textRef = useRef(null);
  return (
    <div className="flex justify-center my-16">
      <div className="form-control items-center lg:items-start">

        {/* controlled field */}
        {/* <input value={inputValue} onChange={e => setInputValue(e.target.value)} type="text" placeholder="Text" className="input input-bordered " /> */}

        {/* ============================================================= */}
        {/* uncontrolled field */}
        <input ref={textRef} defaultValue="Default Value" type="text" placeholder="Text" className="input input-bordered " />
      </div>
    </div>
  );
}

export default App

Here, in this case, we are not dependent on the state of the input field. But we have created a reference to get the input value and set a default value for that input field. This is not being changed by the react state. Hence makes it an uncontrolled component.

Stateless and Stateful components in reactJS

Now, what is a stateless and stateful component in react? Simply put, any component, where a state will be declared and that will be used as well on that component is a stateful component.

If we take a look at the below code,

import React, { useState, useEffect } from "react";
import { useRef } from "react";
const App = () => {
  const [inputValue, setInputValue] = useState('stateful')

  return (
    <div className="flex justify-center my-16">
      <div className="form-control items-center lg:items-start">
        <input value={inputValue} type="text" placeholder="Text" className="input input-bordered " />
      </div>
    </div>
  );
}

export default App

Here, we have declared a state variable that contains a default value. And in this very component, we are using this state value as well. That makes it a stateful component.

On the other hand, a stateless component can be any kind of state where,

  • No state has been declared,
  • No state value is being used (as there is no state variable to begin with)

Take the below code for an example,

import React from "react";
const App = () => {

  return (
    <div className="flex justify-center my-16">
      <div className="form-control items-center lg:items-start">
        <input value="default" type="text" placeholder="Text" className="input input-bordered " />
      </div>
    </div>
  );
}

export default App

Here, as we can see no state has been declared nor used. Hence that makes it a stateless component. It is also known as a dumb component as well.