I want to toggle only the last span element that says "text to toggle for {user.id}", I only want to toggle this element for that specific li element, not all the li elements. Currently how I have set up, it will toggle that span element for all the li elements due to how state works. I was thinking of passing an index via the map function and referencing the index to toggle the element I want, but how can I do that? Because the state is set for all the li elements, is there a better way to do this rather than using state?
I know with vanilla JS I could just use getElementById and set the style of it to hide or block. But with react I wasn't sure the best way to handle this, because I was taught we want to avoid IDs when we can with react. Then as far as using useRef() goes I wasn't sure that would really work here because I would need to create a refs for each element and I don't know that I can do that dynamically or if that would be the best practice for that matter?
Thank you!
import React, { useState } from 'react';
const Users = [
{ id: 1, name: 'Andy', age: 32 },
{ id: 2, name: 'Bob', age: 30 },
{ id: 3, name: 'Tom Hulk', age: 40 },
{ id: 4, name: 'Tom Hank', age: 50 },
{ id: 5, name: 'Audra', age: 30 },
{ id: 6, name: 'Anna', age: 68 },
{ id: 7, name: 'Tom', age: 34 },
{ id: 8, name: 'Tom Riddle', age: 28 },
{ id: 9, name: 'Bolo', age: 23 },
];
function Test() {
const [toggle, setToggle] = useState('none');
function toggleFunction () {
toggle === 'none' ? setToggle('block') : setToggle('none')
}
return (
<div className="container">
<div className="user-list">
{
Users.map((user) => (
<li key={user.id} className="user">
<button onClick={toggleFunction}>Button</button>
<span className="user-id">{user.id}</span>
<span className="user-name">{user.name}</span>
<span className="user-age">{user.age} year old</span>
<span style={{display: toggle}}>text to toggle for {user.id}</span>
</li>
))
}
</div>
</div>
);
}
export default Test;
CodePudding user response:
You want to keep track of toggle state for each element.
export default function App() {
const [toggle, setToggle] = React.useState({});
function toggleFunction(id) {
setToggle({
...toggle,
[id]: !toggle[id],
});
}
return (
<div className="container">
<div className="user-list">
{Users.map((user) => (
<li key={user.id} className="user">
<button onClick={() => toggleFunction(user.id)}>Button</button>
<span className="user-id">{user.id}</span>
<span className="user-name">{user.name}</span>
<span className="user-age">{user.age} year old</span>
<span style={{ display: toggle[user.id] ? 'block' : 'none' }}>
text to toggle for {user.id}
</span>
</li>
))}
</div>
</div>
);
}
toggle
keeps track of which items were toggled or not, by associating id
of an item with its toggle state (we use bracket notation for storing this info), e.g.
{8: true, 9: true}
Then in render we read toggle value of an item using its id
to check if it was toggled or not using toggle[user.id]