Instead of passing multiple props, the parent component manages the state, and child components communicate implicitly.
We break the component into self-contained components
import { createContext, useContext, useState } from "react";
const CartContext = createContext();
const Cart = ({ children }) => {
const [items, setItems] = useState([
{ id: 1, name: "React Book", price: 30 },
{ id: 2, name: "JavaScript Guide", price: 25 }
]);
const removeItem = (id) => {
setItems(items.filter(item => item.id !== id));
};
const total = items.reduce((sum, item) => sum + item.price, 0);
return (
<CartContext.Provider value={{ items, removeItem, total }}>
<div>
<h2>Shopping Cart</h2>
{children}
</div>
</CartContext.Provider>
);
};
Cart.Item = ({ item }) => {
return (
<div>
{item.name} - ${item.price}
<Cart.RemoveButton id={item.id} />
</div>
);
};
Cart.Total = () => {
const { total } = useContext(CartContext);
return <h3>Total: ${total}</h3>;
};
Cart.RemoveButton = ({ id }) => {
const { removeItem } = useContext(CartContext);
return <button onClick={() => removeItem(id)}>Remove</button>;
};
- It allows consumers to define
TabList
, Tab andTabPanel
without explicit prop drilling. - The Tabs parent manages active state and exposes subcomponents.
Tabs (Parent): Manages active state.
Tabs.List: Holds multiple Tab
elements.
Tabs.Tab: Represents an individual tab button.
Tabs.panel: Displays the content of the active tab.
import { createContext, useContext, useState } from "react";
const TabsContext = createContext();
const Tabs = ({ children }) => {
const [activeTab, setActiveTab] = useState(0);
return (
<TabsContext.Provider value={{ activeTab, setActiveTab }}>
<div>{children}</div>
</TabsContext.Provider>
);
};
Tabs.List = ({ children }) => <div>{children}</div>;
Tabs.Tab = ({ index, children }) => {
const { activeTab, setActiveTab } = useContext(TabsContext);
return (
<button
onClick={() => setActiveTab(index)}
style={{ fontWeight: activeTab === index ? "bold" : "normal" }}
>
{children}
</button>
);
};
Tabs.Panel = ({ index, children }) => {
const { activeTab } = useContext(TabsContext);
return activeTab === index ? <div>{children}</div> : null;
};
import Tabs from "./Tabs";
const App = () => (
<Tabs>
<Tabs.List>
<Tabs.Tab index={0}>Tab 1</Tabs.Tab>
<Tabs.Tab index={1}>Tab 2</Tabs.Tab>
<Tabs.Tab index={2}>Tab 3</Tabs.Tab>
</Tabs.List>
<Tabs.Panel index={0}>Content for Tab 1</Tabs.Panel>
<Tabs.Panel index={1}>Content for Tab 2</Tabs.Panel>
<Tabs.Panel index={2}>Content for Tab 3</Tabs.Panel>
</Tabs>
);
export default App;