Controlled & Uncontrolled Component

Jorjis Hasan - Jun 3 - - Dev Community

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.

👉🏽 App.js
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;

Enter fullscreen mode Exit fullscreen mode

Uncontrolled component DevView


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.

👉🏽 App.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;

Enter fullscreen mode Exit fullscreen mode

Controlled component DevView


NB: In case anyone is wondering how I got this developer view, it's actually a Chrome extension called React Developer Tools, available in the extension store.

. . . . . . . . . . . . . . .
Terabox Video Player