Today, we’re diving into a common React challenge: how to toggle multiple items independently within an array. You know, like those cool expandable menus where you can open and close different sections without affecting the others? Yeah, that’s what we’re talking about!
The Challenge: A Programming Languages Menu
Imagine we’re building a dev resource app (because who doesn’t love organizing their coding knowledge, right?). We want to create a menu that looks something like this:
Programming Languages
├─ Frontend +
├─ Backend -
│ ├─ Python
│ └─ Ruby
└─ Mobile +
Each language category can be expanded or collapsed independently. Let’s break down how to toggle these array items separately in React!
Step 1: Setting Up Our Array Data
First things first, let’s define our data structure. We’ll use an array of objects, where each object represents a language category:
const menuItems = [
{
category: 'Frontend',
items: ['JavaScript', 'TypeScript', 'React'],
},
{
category: 'Backend',
items: ['Python', 'Ruby', 'Node.js'],
},
{
category: 'Mobile',
items: ['Swift', 'Kotlin', 'React Native'],
},
];
Step 2: The Naive Approach (Spoiler: It Doesn’t Work)
You might be tempted to use a single boolean state to handle the toggling. Let’s see why that doesn’t cut it:
function App() {
const [isOpen, setIsOpen] = useState(false);
return (
<div className="App">
<h1>Programming Languages</h1>
<ul>
{menuItems.map((menu) => (
<li key={menu.category}>
<button onClick={() => setIsOpen(!isOpen)}>
{menu.category} {isOpen ? '-' : '+'}
</button>
{isOpen && (
<ul>
{menu.items.map((item) => (
<li key={item}>{item}</li>
))}
</ul>
)}
</li>
))}
</ul>
</div>
);
}
If you try this out, you’ll notice all categories open and close together. Not quite what we want, right?
Step 3: The Smart Solution: Object State
Here’s where it gets interesting. Instead of a single boolean, we’ll use an object to keep track of the open/closed state for each category:
function App() {
const [isOpen, setIsOpen] = useState({});
const toggleOpen = (category) => {
setIsOpen((prevState) => ({
...prevState,
[category]: !prevState[category],
}));
};
return (
<div className="App">
<h1>Programming Languages</h1>
<ul>
{menuItems.map((menu) => (
<li key={menu.category}>
<button onClick={() => toggleOpen(menu.category)}>
{menu.category} {isOpen[menu.category] ? '-' : '+'}
</button>
{isOpen[menu.category] && (
<ul>
{menu.items.map((item) => (
<li key={item}>{item}</li>
))}
</ul>
)}
</li>
))}
</ul>
</div>
);
}
Breaking Down Our React Toggle Array Items Solution
- We initialize
isOpen
as an empty object. This will store the open/closed state for each category. - Our
toggleOpen
function updates the state for a specific category, flipping its boolean value. - We use
isOpen[menu.category]
to check if a category should be expanded or not.
And there we go! Now each category toggles independently. 🎉
Demo time:
I made a demo for you to visualize the approach easily. Try clicking on each menu button to see the action.
See the Pen SettingUpReact by Ivo Culic (@ifkas) on CodePen.
Why This Method to Toggle Array Items in React Works
Using an object, we create a dynamic set of boolean flags, one for each category. It’s like having multiple light switches instead of one master switch for the whole house. The key is to have a data structure that can maintain independent states for each category.
Bonus Tips for Toggling Array Items in React:
While we used an object here, you could also solve this with:
- A
Set
to store open categories. - An array of open category names.
- A
Map
object.
You’ve just leveled up your React skills by learning to toggle multiple items independently. This pattern is super useful for all sorts of UI components – accordions, nested menus, language selectors, you name it!
Remember, when dealing with multiple states in React, think beyond simple booleans. Objects, arrays, and other data structures can be your best friends.
Learn more:
- Data types and structures: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures