There are times when we'll have a component whose internal state we want to override. We'll also want to compel the parent component to open it. Let's first take a look at controlled and uncontrolled components.
A controlled component uses props to get its current value, and callbacks are used to notify changes. By processing the callback, managing its state, and delivering the updated values as props to the controlled component, a parent component “controls” it.
Let's say we have an accordion, and we do not want to control the state internally. Instead, we want the parent component to handle the state and the values passed down as props and an onChange
to handle the toggling of the accordion.
App
componentWe have our parent component called App
, and we have the Accordion
component as a child in the App
parent component. We also have an open state and a handleToggle
function, which we pass down as props to the Accordian
component to be able to display the accordion and also toggle the open state.
import { useState } from "react";import Accordion from "./accordion";import "./App.css";function App() {const [open, setOpen] = useState(false);function handleToggle() {setOpen(!open);}return (<div className="App"><Accordion open={open} handleToggle={handleToggle} /></div>);}export default App;
Accordion
componentWe parse the open
and handleToggle
function to the Accordion
component, where the value of the states in the parent component controls the display of the accordion and the toggling of the display component.
import React from "react";const Accordion = ({ open, handleToggle }) => {return (<div style={{ border: "1px solid black" }}>{open && <h1>Accordion 1</h1>}<button onClick={handleToggle}>Toggle</button></div>);};export default Accordion;
The Control Props pattern from the code above allows the parent component to control state values within the child component completely.
An uncontrolled component is the opposite of a controlled component, and allows a component to handle its own state values and functions. Most of the state manipulation is done in the component itself.
Let's use the Accordion
component again to demonstrate this.
import React from "react";const Accordion = () => {const [open, setOpen] = useState(false);function handleToggle() {setOpen(!open);}return (<div style={{ border: "1px solid black" }}>{open && <h1>Accordion 1</h1>}<button onClick={handleToggle}>Toggle</button></div>);};export default Accordion;
The parent component no longer controls the child component. The child component handles its state and functionality internally.
We can use the mixed control component in an uncontrolled or controlled manner. It receives the prop’s initial value and sets it in the state. It then reacts to changes in props through useEffect
to bring the state up to date with the props.