Reactjs:使用状态挂钩单击时如何选择一张或多张卡片?
Posted
技术标签:
【中文标题】Reactjs:使用状态挂钩单击时如何选择一张或多张卡片?【英文标题】:Reactjs: How to select one or multiple cards when clicked with a state hook? 【发布时间】:2021-09-22 03:00:00 【问题描述】:我有一个卡片组件 TemplateList 用于映射我的模板卡片(我通过数组添加它们)。
我想添加一个 onClick 状态挂钩功能,帮助我在点击时选择一张或多张卡片,我该怎么做?
这是我的 TemplateList 组件:
import TemplateCard from
import styles from "./styles/actionpage.m.css";
export type Template =
title: string;
description: string;
imgURL: string;
;
type Props =
templates: Template[];
;
const TemplateList = ( templates : Props) =>
return (
<div className=styles.scrollContainer>
templates.map((item) => (
<TemplateCard
title=item.title
description=item.description
img=item.imgURL
classNameToAdd=styles.cardContainer
/>
))
</div>
);
;
export default TemplateList;
这是我的 TemplateCard 组件:
import React from "react";
import styles from "./styles/cards.m.css";
type Props =
title: string;
description: string;
img: string;
classNameToAdd?: string;
selected?: boolean;
classNameOnSelected?: string;
;
const TemplateCard = (
title,
description,
img,
classNameToAdd,
classNameOnSelected,
selected,
: Props) =>
const aspectRatio, vmin = useWindowResponsiveValues();
let className = `$styles.card $classNameToAdd`;
if (selected)
className += `$styles.card $classNameToAdd $classNameOnSelected`;
return (
<div style=card className=className>
<img style=imageSize src=img></img>
<div style=cardTitle>title</div>
<div style=descriptionCard>description</div>
</div>
);
;
TemplateCard.defaultProps =
classNameOnSelected: styles.selected,
;
export default TemplateCard;
目前,我添加了一个“已选择”道具,在为真时为我的卡片提供边框,但这当然会在为真时选择所有卡片。
这就是我的卡片在被选中时的样子。
【问题讨论】:
【参考方案1】:要解决这个问题,您必须为每张卡设置自己的状态; selected
。
这样每张卡片都会有自己的小逻辑,通过这些逻辑他们可以知道自己是否被选中。
// TemplateCard.js
...
const TemplateCard = (
title,
description,
img,
classNameToAdd,
classNameOnSelected,
/* selected, we will make this a state instead of prop */
: Props) =>
const aspectRatio, vmin = useWindowResponsiveValues();
const [selected, setSelected] = useState(false); // Added state
// Added handler
const handleClick = () =>
setSelected(!selected);
;
if (selected)
className += `$styles.card $classNameToAdd $classNameOnSelected`;
return (
<div style=card className=className onClick=handleClick>
<img style=imageSize src=img></img>
<div style=cardTitle>title</div>
<div style=descriptionCard>description</div>
</div>
);
;
...
【讨论】:
太棒了!我刚刚添加了它,现在它应该选择我的卡片。不过,我会有一个问题,我在控制台中收到此警告,但不知道为什么会这样: 列表中的每个孩子都应该有一个唯一的“key”道具。检查TemplateList
的渲染方法。有关更多信息,请参阅 react-warning-keys。在 TemplateCard(由 TemplateList 创建)在 TemplateList(由 ActionPageNew 创建)
每当你通过 map 方法渲染一个 React 组件列表时,你还必须为每个 React 组件提供一个 key prop。您可以在 react docs 上找到更多信息。【参考方案2】:
在您的 TemplateCard 组件上添加一个 onClick 处理程序并在主 div 上触发它。此外,您需要为您的个人卡提供一些标识,以便我们可以使用其来源的数组索引。
像这样:
const TemplateCard = (
title,
description,
img,
classNameToAdd,
classNameOnSelected,
selected,
handleClick
index
: Props) =>
const aspectRatio, vmin = useWindowResponsiveValues();
let className = `$styles.card $classNameToAdd`;
if (selected)
className += `$styles.card $classNameToAdd $classNameOnSelected`;
return (
<div style=card className=className onClick=()=>handleClick(index)>
<img style=imageSize src=img></img>
<div style=cardTitle>title</div>
<div style=descriptionCard>description</div>
</div>
);
;
在您的 TemplateList 组件中,您需要设置一个索引数组(使用 useState)来存储单击的 TemplateCards 的索引,以便您可以检查选择了哪些卡,哪些没有。并使用我们传递给子组件的函数设置状态,即handleClick
像这样:
const [selectedArray,setSelectedArray]=useState([])
const handleClick=(i)=>
const tempArray =[...selectedArray]
if(tempArray[i]==i)tempArray[i]=undefined
else tempArray[i]=i
setSelectedArray(tempArray)
组件将是这样的:
const TemplateList = ( templates : Props) =>
return (
<div className=styles.scrollContainer>
templates.map((item,index) => (
<TemplateCard
title=item.title
description=item.description
img=item.imgURL
classNameToAdd=styles.cardContainer
index=index
selected=selectedArray[index]==index? true:false
handleClick=handleClick
/>
))
</div>
);
;
现在这里发生的情况是,我们使用索引作为标识符,并基于此设置选定卡片的数组。在此基础上,我们将 'selected' 属性发送到 Card 组件。在那里,您可以根据该道具应用您的样式。
希望您的问题得到解答!
【讨论】:
以上是关于Reactjs:使用状态挂钩单击时如何选择一张或多张卡片?的主要内容,如果未能解决你的问题,请参考以下文章