无法根据元素类型有条件地更改具有设置状态的样式
Cannot change style with set state conditionally based on type of element
我试图在您使用 changeActivityStyleBasedOnZone 函数单击区域按钮时更改 activity 按钮的颜色。例如,如果我单击类型为“浓度”的区域按钮,我想将 activity 按钮的颜色更改为与类型为“浓度”的按钮相同的颜色。现在,当您单击区域按钮时,所有 activity 按钮都会改变颜色。现在我有一个功能,如果你点击一个 activity 按钮,它会根据 activity 的类型改变颜色,这是我想保留的东西。如何只使与单击区域按钮类型相同的按钮更改颜色而不影响其他 activity 按钮?我还尝试测试按类型过滤活动数组,然后通过过滤数组进行映射以仅在过滤数组上设置状态,但也许这是错误的方法或者我做错了,因为映射似乎不起作用.
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;
}
试试这个 link 并告诉我应用程序是否应该这样工作。
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 link 您可以添加您的样式并按您的方式进行测试。
https://replit.com/@pskath1/GrowingIllfatedRate?v=1
这里有很多问题。我将尝试以合理的顺序解决它们,然后在最后提供示例代码。
问题
1.所有按钮都因为这一行而变色:
className={clickedActivityIndex === index | zoneClicked === true ? activityStyle: 'activity'}
如果zoneClicked
是true
,存储在activityStyle
中的class将应用于所有按钮。同时,一旦调用 changeActivityStyleBasedOnZone
,zoneClicked
就会设置为 true
:
const changeActivityStyleBasedOnZone = (zoneType) => {
setZoneClicked(true);
...
}
2.changeActivityStyle
和changeActivityStyleBasedOnZone
相互冲突
它们都更改 activityStyle
,因此当前值将应用于具有匹配条件的按钮并覆盖先前的 class 值。这在逻辑上是混乱的,让人不清楚 changeActivityStyle
的意义是什么。我的假设是您想对所选区域应用不同的样式 activity,独立于所选区域样式。
3. changeActivityStyle
和 changeActivityStyleBasedOnZone
中的 if
块是不必要的,会使代码复杂化。
这个特定的块有问题。它多次将相同的值应用于 activityStyle
。我从我的解决方案中完全删除了它,但我想让你知道这一点。
if (zoneType === "concentration") {
const concentrationActivities = activities.filter(
(activity) => activity.type === "concentration"
);
concentrationActivities.map((ca) => {
setActivityStyle("activity-concentration");
});
}
4. zoneType
和 activityType
无效 html button
属性。
使用 data-
属性创建自定义属性。名称必须全部小写。例如data-activity-type
和 data-zone-type
解决方法
正如我所说,我不完全确定你的目标,而且我没有你的 CSS,所以你需要根据你的用例进行调整。也就是说,我认为它会让你接近。
这里是 CodeSandbox 的完整示例。我添加了一个 table 来显示状态值。
首先,我改变了changeActivityStyle
和changeActivityStyleBasedOnZone
:
const changeActivityStyle = (index) => {
setClickedActivityIndex(index);
};
const changeActivityStyleBasedOnZone = (zone) => {
setZoneClicked(zone);
return;
};
您会注意到这意味着 zoneClicked
现在存储整个 zone
对象。因此,将 useState
挂钩更改为:
const [zoneClicked, setZoneClicked] = useState({});
并且区域按钮 onClick
更改为:
onClick={() => changeActivityStyleBasedOnZone(zone)}
然后我像这样更改了 activity 按钮 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}
>
使用模板文字,我们可以根据两种条件应用两种不同的 classes,一种与选定区域相关,一种与选定区域相关 activity。
由于 zoneClicked
现在存储整个区域,我只是将所选区域的 styleType
应用为 class 名称。
如果选定的 activity 索引匹配,我会应用额外的 class 来突出显示选定的按钮。在这种情况下,class 只是删除边框,但您可以应用任何您想要的样式。请注意 selected
class 中的 !important
运算符 - 这可确保区域 class 在以后应用时不会覆盖它。
我试图在您使用 changeActivityStyleBasedOnZone 函数单击区域按钮时更改 activity 按钮的颜色。例如,如果我单击类型为“浓度”的区域按钮,我想将 activity 按钮的颜色更改为与类型为“浓度”的按钮相同的颜色。现在,当您单击区域按钮时,所有 activity 按钮都会改变颜色。现在我有一个功能,如果你点击一个 activity 按钮,它会根据 activity 的类型改变颜色,这是我想保留的东西。如何只使与单击区域按钮类型相同的按钮更改颜色而不影响其他 activity 按钮?我还尝试测试按类型过滤活动数组,然后通过过滤数组进行映射以仅在过滤数组上设置状态,但也许这是错误的方法或者我做错了,因为映射似乎不起作用.
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;
}
试试这个 link 并告诉我应用程序是否应该这样工作。 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 link 您可以添加您的样式并按您的方式进行测试。 https://replit.com/@pskath1/GrowingIllfatedRate?v=1
这里有很多问题。我将尝试以合理的顺序解决它们,然后在最后提供示例代码。
问题
1.所有按钮都因为这一行而变色:
className={clickedActivityIndex === index | zoneClicked === true ? activityStyle: 'activity'}
如果zoneClicked
是true
,存储在activityStyle
中的class将应用于所有按钮。同时,一旦调用 changeActivityStyleBasedOnZone
,zoneClicked
就会设置为 true
:
const changeActivityStyleBasedOnZone = (zoneType) => {
setZoneClicked(true);
...
}
2.changeActivityStyle
和changeActivityStyleBasedOnZone
相互冲突
它们都更改 activityStyle
,因此当前值将应用于具有匹配条件的按钮并覆盖先前的 class 值。这在逻辑上是混乱的,让人不清楚 changeActivityStyle
的意义是什么。我的假设是您想对所选区域应用不同的样式 activity,独立于所选区域样式。
3. changeActivityStyle
和 changeActivityStyleBasedOnZone
中的 if
块是不必要的,会使代码复杂化。
这个特定的块有问题。它多次将相同的值应用于 activityStyle
。我从我的解决方案中完全删除了它,但我想让你知道这一点。
if (zoneType === "concentration") {
const concentrationActivities = activities.filter(
(activity) => activity.type === "concentration"
);
concentrationActivities.map((ca) => {
setActivityStyle("activity-concentration");
});
}
4. zoneType
和 activityType
无效 html button
属性。
使用 data-
属性创建自定义属性。名称必须全部小写。例如data-activity-type
和 data-zone-type
解决方法
正如我所说,我不完全确定你的目标,而且我没有你的 CSS,所以你需要根据你的用例进行调整。也就是说,我认为它会让你接近。
这里是 CodeSandbox 的完整示例。我添加了一个 table 来显示状态值。
首先,我改变了changeActivityStyle
和changeActivityStyleBasedOnZone
:
const changeActivityStyle = (index) => {
setClickedActivityIndex(index);
};
const changeActivityStyleBasedOnZone = (zone) => {
setZoneClicked(zone);
return;
};
您会注意到这意味着 zoneClicked
现在存储整个 zone
对象。因此,将 useState
挂钩更改为:
const [zoneClicked, setZoneClicked] = useState({});
并且区域按钮 onClick
更改为:
onClick={() => changeActivityStyleBasedOnZone(zone)}
然后我像这样更改了 activity 按钮 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}
>
使用模板文字,我们可以根据两种条件应用两种不同的 classes,一种与选定区域相关,一种与选定区域相关 activity。
由于 zoneClicked
现在存储整个区域,我只是将所选区域的 styleType
应用为 class 名称。
如果选定的 activity 索引匹配,我会应用额外的 class 来突出显示选定的按钮。在这种情况下,class 只是删除边框,但您可以应用任何您想要的样式。请注意 selected
class 中的 !important
运算符 - 这可确保区域 class 在以后应用时不会覆盖它。