Reputation: 978
This is probably really easy, I want to show the info of a list item when a user clicks on the item, however, the code I have will open the info of all list items when clicked.
https://codesandbox.io/s/friendly-lichterman-j1vpd?file=/src/App.js:0-599
import React, { useState } from "react";
import "./styles.css";
const list = [1, 2, 3];
export default function App() {
const [active, setActive] = useState(false);
return (
<div>
{list.map((item, idx) => {
return (
<>
<li
onClick={() => {
setActive(!active);
}}
>
{item}
<div className={active ? "active" : "info"}>
{" "}
Info {idx + 1}
</div>
</li>
</>
);
})}
</div>
);
}
Upvotes: 1
Views: 2555
Reputation: 11
You can follow this method too
const list = ['Start', 'Installation', 'Text Banners', 'Image Banners'];
const links = ['/start', '/installation', '/textbanners', '/imagebanners'];
const [active, setActive] = useState(null)
const toggleActive = (e) => {
console.log(e)
setActive(e.target.innerText)
}
return (
<div className={style.dashboard_container}>
<div className={style.dashboard}>
<ul>
{list.map((item, index) => {
return (
<li className={active == item ? style.active : ''} key={index} onClick={toggleActive}>{item}</li>
)
})}
</ul>
</div>
{children}
</div>
);
Upvotes: 1
Reputation: 7915
Seems like a good use case for useReducer. It's a really useful tool to keep track of the states of multiple components. In your case you would need to track whether a given LI is active (showing information) or not. Here is how to do that with useReducer
along with a Sanbdox
import React, { useState } from "react";
import "./styles.css";
const list = [1, 2, 3];
const default_states = list.map((item) => Object({ id: item, action: false }));
export default function App() {
const [li_states, dispatch] = React.useReducer((state, id) => {
return state.map((item) => {
if (item.id === id) return { id: item.id, active: !item.active };
else return item;
});
}, default_states);
return (
<div>
{list.map((item) => {
const cur = li_states.find((s) => s.id === item);
return (
<div key={item}>
<li
onClick={() => {
dispatch(item);
}}
>
{item}
</li>
<div className={cur.active ? "action" : "info"}> Info {item}</div>
</div>
);
})}
</div>
);
}
What's happening here is each time you click any of your LIs, the dispatch
calls the reducer function inside React.useReducer
with the ID of the LI and toggles the state of the clicked LI.
Upvotes: 1
Reputation: 239
You are trying to toggle active only which is used by all items. Instead use index position to toggle.
I have explained the rest within the code using comments.
App.js
import React, { useState } from "react";
import "./styles.css";
const list = [1, 2, 3];
export default function App() {
const [active, setActive] = useState();
return (
<div>
{/* You forgot to add ul here */}
<ul>
{list.map((item, idx) => {
return (
// Added key to each child to avoid error. Use <React.Fragment/> instead of <>
<React.Fragment key={idx}>
<li
onClick={() => {
// Condition for toggling the lists.
// If current list is selected
if (active === idx) {
// change active to blank
setActive();
} else {
// change active to current index
setActive(idx);
}
}}
>
{item}
</li>
<div className={active === idx ? "info active" : "info"}>
{" "}
Info {idx + 1}
</div>
</React.Fragment>
);
})}
</ul>
</div>
);
}
Edited this css to avoid applying to another tag style.css
.info.active {
display: flex;
}
You can try the above code on sandbox https://codesandbox.io/s/stackoverflow-qno-65730790-tmeyf
Upvotes: 1