【问题标题】:How to toggle class of a single element in a .map() function?如何在 .map() 函数中切换单个元素的类?
【发布时间】:2021-10-12 21:04:52
【问题描述】:
我正在尝试为循环内的特定元素切换类。
const ItemList: React.FC<ListItemUserProps> = (props) => {
const { items } = props;
const [showUserOpt, setShowUserOpt] = useState<boolean>(false);
function toggleUserOpt() {
setShowUserOpt(!showUserOpt);
}
const userOptVisible = showUserOpt ? 'show' : 'hide';
return (
<>
{items.map((t) => (
<React.Fragment key={t.userId}>
<div
className={`item ${userOptVisible}`}
role="button"
tabIndex={0}
onClick={() => toggleUserOpt()}
onKeyDown={() => toggleUserOpt()}
>
{t.userNav.firstName}
</div>
</React.Fragment>
))}
</>
);
};
export default ItemList;
当我单击一个元素时,该类会为每个元素切换。
【问题讨论】:
标签:
reactjs
react-native
react-redux
【解决方案1】:
您可以创建另一个组件,该组件可以拥有自己的状态,可以在不影响其他同级组件状态的情况下进行切换:
孩子:
const ItemListItem: React.FC<SomeInterface> = ({ item }) => {
const [show, setShow] = useState<boolean>(false);
const userOptVisible = show ? "show" : "hide";
const toggleUserOpt = (e) => {
setShow((prevState) => !prevState);
};
return (
<div
className={`item ${userOptVisible}`}
role="button"
tabIndex={0}
onClick={toggleUserOpt}
onKeyDown={toggleUserOpt}
>
{item.userNav.firstName}
</div>
);
};
家长:
const ItemList: React.FC<ListItemUserProps> = ({ items }) => {
return (
<>
{items.map((t) => (
<ItemListItem key={t.userId} item={t} />
))}
</>
);
};
【解决方案2】:
如果您只是向元素添加类,我会保持简单并使用处理程序使用纯 JS 切换类。
const handleClick = (e) => {
// example of simply toggling a class
e.currentTarget.classList.toggle('selected');
};
演示:
const {
useState,
} = React;
// dummy data
const data = Array(20).fill(null).map((i, index) => `item ${(index + 1).toString()}`);
function App() {
const [items, setItems] = useState(data);
const handleClick = (e) => {
e.currentTarget.classList.toggle('selected');
};
return (
<div>
{items.map((item) => (
<button key={item} onClick={handleClick}>{item}</button>
))}
</div>
);
}
ReactDOM.render( <
App / > ,
document.getElementById("app")
);
.selected {
background: red;
}
<script crossorigin src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>
<div id="app"></div>
【解决方案3】:
我认为最好跟踪索引,以便可以针对列表中的单个项目。就目前而言,boolean 将更改所有人的样式,因为您尚未指定哪个应该获得className。
添加一个useState 挂钩来跟踪它,例如:
const [activeIndex, setActiveIndex] = useState(null);
然后新建一个函数:
function handleIndexOnClick(index) {
setActive(index);
}
然后在您的map() 函数中添加index。然后,您需要将 index 传递给您的 className 属性和 onClick 函数。该位的最终结果应如下所示:
{items.map((t, index) => (
<React.Fragment key={t.userId}>
<div
className={`item ${activeIndex && items[activeIndex] ? 'show' : 'hide }`}
role="button"
tabIndex={0}
onClick={() => handleIndexOnClick(index)}
onKeyDown={() => toggleUserOpt()}
>
{t.userNav.firstName}
</div>
</React.Fragment>
))}