无法根据元素的类型有条件地更改设置状态的样式



当您使用changeActivityStyleBasedOnZone函数单击区域按钮时,我正在尝试更改活动按钮的颜色。例如,如果我点击一个区域按钮;"浓度";如果活动按钮具有类型",我想将它们的颜色更改为相同的颜色;浓度";。现在,当您单击区域按钮时,所有活动按钮都会更改颜色。现在我有一个功能,如果你点击一个活动按钮,它会根据活动的类型而改变颜色,这是我想要保留的。如何在不影响其他活动按钮的情况下,仅使与单击的区域按钮类型相同的按钮更改颜色?我还尝试过对类型上的活动数组进行过滤,然后通过过滤后的数组进行映射,以仅在过滤后的阵列上设置状态,但可能这是错误的方法,或者我做得不对,因为映射似乎不起作用。

import React, { useState } from 'react';
const Game = (activityType) => {
const [activityStyle, setActivityStyle] = useState("activity");
const [zoneClicked, setZoneClicked] = useState(false);
const [clickedActivityIndex, setClickedActivityIndex] = useState(-1);
const zones = [
{id: 1, name: "Concentration", styleType: "concentration-zone", type: "concentration" },
{id: 2, name: "Communication", styleType: "communication-zone", type: "communication"},
{id: 3, name: "Collaboration", styleType: "collaboration-zone",  type: "collaboration"},
{id: 4, name: "Chill Out", styleType: "chill-out-zone", type: "chillout"},
{id: 5, name: "Camp", styleType: "camp-zone", type: "camp"}
]
const activities = [
{id: 1, name: "Code", type: "concentration"},
{id: 2, name: "Teams Meeting", type: "communication"},
{id: 3, name: "Make a phone call", type: "camp"},
{id: 4, name: "Work shops with colleagues", type: "collaboration"},
{id: 5, name: "Coffee break", type: "chillout"},
{id: 6, name: "Lively discussions & brainstorming", type: "collaboration"},
]
const changeActivityStyle = (activityType, index) => {
setClickedActivityIndex(index);
if (activityType === "concentration") {
setActivityStyle("activity-concentration");
setClickedActivityIndex(0) ;
}
if (activityType === "communication") {
setActivityStyle("activity-communication");
}
if (activityType === "camp") {
setActivityStyle("activity-camp");
}
if (activityType === "chillout") {
setActivityStyle("activity-chill-out");
} 
if (activityType === "collaboration") {
setActivityStyle("activity");
}
return;
};
const changeActivityStyleBasedOnZone = (zoneType) => {
setZoneClicked(true);
if (zoneType === "concentration") {
const concentrationActivities = activities.filter(activity => activity.type === "concentration");
concentrationActivities.map((ca) => {
setActivityStyle("activity-concentration");
}); 
}

if (zoneType === "communication") {
setActivityStyle("activity-communication");
}
if (zoneType === "camp") {
setActivityStyle("activity-camp");
}
if (zoneType === "chillout") {
setActivityStyle("activity-chill-out");
}
if (zoneType === "collaboration") {
setActivityStyle("activity");
}
return;
}
return (
<>
<section className="header"><h2>Click on an activity box to see which area it belongs to</h2></section>
<section className="game-area">
<div className="activity-zone-container">
<div className="zone-container">
{zones.map((zone =>
<button 
className="zone" 
id={zone.styleType} 
key={zone.id}
zoneType={zone.type}
onClick={() => changeActivityStyleBasedOnZone(zone.type, 
activityType)}
>
<p>{zone.name}</p>
</button>
))}
</div>
<div className="activity-container">
{activities.map((activity, index) => 
<button 
className={clickedActivityIndex === index | zoneClicked === true ? activityStyle: 'activity'} 
onClick={() => changeActivityStyle(activity.type, index)} 
key={activity.id}
activityType={activity.type}>
<p>{activity.name}</p>
</button>
)}
</div>        
</div>
</section>
</>
);
};

CSS

#concentration-zone {
background-color: orange;
}
#communication-zone {
background-color: yellow;
}
#communication-zone p {
color: black;
}
#collaboration-zone {
background-color: #3260a8;
}
#chill-out-zone {
background-color: pink;
}
#chill-out-zone p {
color: black;
}
#camp-zone {
background-color: green;
}
.activity {
background-color: #3260a8;
margin: 17px;
display: flex;
justify-content: center;
cursor: pointer;
width: 140px;
height: 87px;
}
.activity-concentration {
background-color: orange;
margin: 17px;
display: flex;
justify-content: center;
color: white;
width: 140px;
height: 87px;
}
.activity-communication {
background-color: yellow;
margin: 17px;
display: flex;
justify-content: center;
width: 140px;
height: 87px;
}
.activity-chill-out {
background-color: pink;
margin: 17px;
display: flex;
justify-content: center;
width: 140px;
height: 87px;
}
.activity-camp {
background-color: green;
margin: 17px;
display: flex;
justify-content: center;
color: white;
width: 140px;
height: 87px;
}

这里有很多问题。我将尝试以合理的顺序处理它们,然后在最后提供示例代码。

问题

1。由于以下行,所有按钮都在变色:

className={clickedActivityIndex === index | zoneClicked === true ? activityStyle: 'activity'}

如果zoneClickedtrue,则存储在activityStyle中的类将应用于所有按钮。同时,一旦调用changeActivityStyleBasedOnZonezoneClicked就被设置为true

const changeActivityStyleBasedOnZone = (zoneType) => {
setZoneClicked(true);
...
}

2。changeActivityStylechangeActivityStyleBasedOnZone相互冲突。

它们都会更改activityStyle,因此当前值将应用于具有匹配条件的按钮,并覆盖以前的类值。这在逻辑上很混乱,不清楚changeActivityStyle的意义所在。我的假设是,您希望将不同的样式应用于所选活动,而与所选区域样式无关。

3。changeActivityStylechangeActivityStyleBasedOnZone中的if块是不必要的,并且使代码复杂化。

这个特定的区块是有问题的。它多次将相同的值应用于activityStyle。我把它从我的解决方案中完全删除了,但我想让你知道这一点。

if (zoneType === "concentration") {
const concentrationActivities = activities.filter(
(activity) => activity.type === "concentration"
);
concentrationActivities.map((ca) => {
setActivityStyle("activity-concentration");
});
}

4.zoneTypeactivityType不是有效的htmlbutton属性。

使用data-属性创建自定义属性。名称必须全部为小写字母。例如data-activity-typedata-zone-type


解决方案

正如我所说,我不完全确定你的目标,而且我没有你的CSS,所以你需要根据你的用例调整它。也就是说,我认为这会让你接近。

下面是一个带有完整示例的CodeSandbox。我添加了一个表来显示状态值。

首先,我将changeActivityStylechangeActivityStyleBasedOnZone更改为:

const changeActivityStyle = (index) => {
setClickedActivityIndex(index);
};
const changeActivityStyleBasedOnZone = (zone) => {
setZoneClicked(zone);
return;
};

您会注意到这意味着zoneClicked现在存储整个zone对象。因此,将useState挂钩更改为:

const [zoneClicked, setZoneClicked] = useState({});

区域按钮onClick变为:

onClick={() => changeActivityStyleBasedOnZone(zone)}

然后我更改了活动按钮className,如下所示:

<button
className={
`${activity.type === zoneClicked.type ? zoneClicked.styleType :"activity"} 
${clickedActivityIndex === index ? "selected" : ""}`
}
onClick={(e) => changeActivityStyle(index)}
key={activity.id}
data-activity-type={activity.type}
>

使用模板文字,我们可以基于两个条件应用两个不同的类,一个与所选区域相关,另一个与选定活动相关。

由于zoneClicked现在存储整个区域,所以我只应用所选区域的styleType作为类名。

如果选定的活动索引匹配,我将应用一个附加类来突出显示选定的按钮。在这种情况下,类只是删除了边框,但您可以应用任何您想要的样式。请注意selected类中的!important运算符,这样可以确保区域类在以后应用时不会覆盖它。

尝试这个链接,告诉我应用程序是否应该这样工作。https://growingillfatedrate.pskath1.repl.co/

这是的工作代码

import React,{ useState } from 'react';
const activities = [
{id: 1, name: "Code", type: "concentration"},
{id: 2, name: "Teams Meeting", type: "communication"},
{id: 3, name: "Make a phone call", type: "camp"},
{id: 4, name: "Work shops with colleagues", type: "collaboration"},
{id: 5, name: "Coffee break", type: "chill-out"},
{id: 6, name: "Lively discussions & brainstorming", type: "collaboration"},
];

const zones = [
{id: 1, name: "Concentration", styleType: "concentration-zone", type: "concentration" },
{id: 2, name: "Communication", styleType: "communication-zone", type: "communication"},
{id: 3, name: "Collaboration", styleType: "collaboration-zone",  type: "collaboration"},
{id: 4, name: "Chill Out", styleType: "chill-out-zone", type: "chill-out"},
{id: 5, name: "Camp", styleType: "camp-zone", type: "camp"}
];



const Game = () => {
const [activityStyle, setActivityStyle] = useState("activity");
const [zoneClicked, setZoneClicked] = useState(false);
const [clickedActivityIndex, setClickedActivityIndex] = useState(-1);

const changeActivityStyle = (activityType, index) => {
setClickedActivityIndex(index);
if (activityType === "concentration") {
setActivityStyle("concentration");
setClickedActivityIndex(0) ;
}
if (activityType === "communication") {
setActivityStyle("communication");
}
if (activityType === "camp") {
setActivityStyle("camp");
}
if (activityType === "chillout") {
setActivityStyle("chill-out");
} 
if (activityType === "collaboration") {
setActivityStyle("collaboration");
}

if (activityType === "chill-out") {
setActivityStyle("chill-out");
}
return;
};
const changeActivityStyleBasedOnZone = (zoneType) => {
setZoneClicked(true);
if (zoneType === "concentration") {
setActivityStyle("concentration")
}

if (zoneType === "communication") {
setActivityStyle("communication");
}
if (zoneType === "camp") {
setActivityStyle("camp");
}
if (zoneType === "chill-out") {
setActivityStyle("chill-out");
}
if (zoneType === "collaboration") {
setActivityStyle("collaboration");
}
return;
}
return (
<>
<section className="header"><h2>Click on an activity box to see which area it belongs to</h2></section>
<section className="game-area">
<div className="activity-zone-container">
<div className="zone-container">
{zones.map((zone =>
<button 
className={zone.type} 
id={zone.styleType} 
key={zone.id}
zoneType={zone.type}
onClick={() => changeActivityStyleBasedOnZone(zone.type)}
>
<p>{zone.name}</p>
</button>
))}
</div>
<div className="activity-container">
{activities.map((activity, index) => 
<button 
className={activityStyle == activity.type ? activityStyle: '' } 
onClick={() => { changeActivityStyle(activity.type, index) }} 
key={activity.id}
activityType={activity.type}>
<p>{activity.name}</p>
</button>
)}
</div>        
</div>
</section>
</>
);
};

还有相同的repl链接,你可以添加你的风格并在路上进行测试。https://replit.com/@pskath1/成长命运多舛日期?v=1

最新更新