Controlled & Uncontrolled Component
Tags: webdev, javascript, react, discuss
Published: 2024-06-03 17:55:59

## Uncontrolled 🔽

In the example, each accordion has its own state(`isOpen`). By default, it is set to `false`. On click, it flips the value of the state variable(`isOpen`) to `true or false`. Based on the `isOpen` value, it expands and collapses. 

Since it controls its own state and doesn't rely on its parents, the children are **uncontrolled components**. 

{% details 👉🏽 App.js %} 

```jsx
const AccordionSection = ({ title, children }) => {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <div>
      <button onClick={() => setIsOpen(!isOpen)}>{title}</button>
      <span>{isOpen && children}</span>
    </div>
  );
};

const UncontrolledAccordion = () => {
  return (
    <div>
      <AccordionSection title="Button 1">Content 1</AccordionSection>
      <AccordionSection title="Button 2">Content 2</AccordionSection>
      <AccordionSection title="Button 3">Content 3</AccordionSection>
    </div>
  );
};

export default UncontrolledAccordion;

```

{% enddetails %}



![Uncontrolled component DevView](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/00zvn1ag67k2xwxid873.gif)

---


## Controlled ⬇️

Unlike an uncontrolled component, if the parent controls the child's state heavily or the child relies on his parent, that child is a Controlled component.

In the example below, we removed the accordion's ability to control itself and gave that power to the parent. Let's inspect the code.

- Render the accordions without functionality.
- Create state variable `activeIndex` with value `null`
- Whenever any accordion gets clicked, the `onClick` function is invoked, and `activeIndex` is set to the current `index`.

- By then, re-render happens. And this props `isActive={activeIndex === index}` validate and send `True` in props. 

- The accordion that gets clicked will get a `True` boolean value and will be expanded.

Even in the preview of our code, we can see that the parent's state changes every time a child clicks. The parent is controlling the child via props.

{% details 👉🏽 App.js %} 

```js
const AccordionSection = ({ title, children, isActive, onClick }) => {
  return (
    <div>
      <button onClick={onClick}>{title}</button>
      {isActive && <span>{children}</span>}
    </div>
  );
};

const ControlledAccordion = () => {
  const [activeIndex, setActiveIndex] = useState(null);

  return (
    <>
      {["Content 1", "Content 2", "Content 3"].map((content, index) => (
        <AccordionSection
          key={index}
          title={`Button ${index + 1}`}
          isActive={activeIndex === index}
          onClick={() => setActiveIndex(activeIndex === index ? null : index)}
        >
          {content}
        </AccordionSection>
      ))}
    </>
  );
};

export default ControlledAccordion;

```

{% enddetails %}


![Controlled component DevView](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4cnnxb8rycbpgqjc210t.gif)


---

NB: In case anyone is wondering how I got this developer view, it's actually a Chrome extension called [React Developer Tools](https://chromewebstore.google.com/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=en), available in the extension store.