JavaScript/React 中的按钮使用 useState 和 useEffect 钩子切换活动按钮?
Switch active buttons using useState and useEffect Hooks for Buttons in JavaScript/React?
我正在尝试编写一个 useState() Hook,并可能添加 useEffect() 来解决两个按钮上的活动状态。 Delivery 按钮需要使用 CSS 更改激活第一个按钮交付,如果单击第二个按钮 PickUp,它应该更改 CSS UI 以保持活动状态。
是的,如果可能的话,我想使用 Hooks。
有什么办法可以这样完成吗?
const Header = props => {
const [isActive, setIsActive] = useState(false);
function changeButtons () {
setIsActive = (!isActive)
};
return (
<Fragment>
<header className={classes.header}>
<div className={classes.logo} onClick={reload}>
<div >
Foodzilla
</div>
</div>
<div className={classes.delivery}>
<div
className={isActive ? classes.deliveryAction : classes.deliveryChoice}
onChange={changeButtons}
>Delivery</div>
<div className={classes.or}>or</div>
<div
className={isActive ? classes.pickUpAction : classes.pickUpChoice}
onChange={changeButtons}
>Pick Up</div>
</div>
好的,所以我做了一个你想要做的模型(我想 :D)。这是工作解决方案的 link:https://codesandbox.io/s/quiet-mountain-68e10k?file=/src/styles.css:59-775.
代码也在下面。确实可以进行一些重构,但我想至少让您走上正确的道路。
快速总结:
蓝色被选中(激活时优先于悬停和默认)。
绿色悬停(在 div 之外时返回默认值)。
红色是默认值(如果未单击或悬停,则显示红色)。
import "./styles.css";
import React, { useState } from "react";
export default function App() {
const [isDeliveryClicked, setIsDeliveryClicked] = useState(false);
const [isPickupClicked, setIsPickupClicked] = useState(false);
const [isDeliveryHovered, setIsDeliveryHovered] = useState(false);
const [isPickupHovered, setIsPickupHovered] = useState(false);
const handleClick = (e) => {
if (e.target.className.includes("delivery")) {
setIsDeliveryClicked(true);
setIsDeliveryHovered(false);
if (isDeliveryClicked === true) {
setIsDeliveryClicked(false);
setIsDeliveryHovered(true)
}
} else if (e.target.className.includes("pickup")) {
setIsPickupClicked(true);
setIsPickupHovered(false);
if (isPickupClicked === true) {
setIsPickupClicked(false);
setIsPickupHovered(true)
}
}
};
const handleOnMouseOver = (e) => {
if (e.target.className.includes("delivery")) {
setIsDeliveryHovered(true);
} else if (e.target.className.includes("pickup")) {
setIsPickupHovered(true);
}
};
const handleOnMouseLeave = (e) => {
if (e.target.className.includes("delivery")) {
setIsDeliveryHovered(false);
} else if (e.target.className.includes("pickup")) {
setIsPickupHovered(false);
}
};
const handleClassStyler = (buttonType) => {
if (buttonType === 'delivery') {
if (isDeliveryClicked === true) {
return "deliveryClicked";
} else if (isDeliveryHovered === true && isDeliveryClicked === false) {
return "deliveryHovered";
} else if (isDeliveryClicked === false && isDeliveryHovered === false) {
return "delivery";
}
} else if (buttonType === 'pickup'){
if (isPickupClicked === true) {
return "pickupClicked";
} else if (isPickupHovered === true && isPickupClicked === false) {
return "pickupHovered";
} else if (isPickupClicked === false && isPickupHovered === false) {
return "pickup";
}
}
};
return (
<div className="App">
<div
onMouseOver={handleOnMouseOver}
onMouseLeave={handleOnMouseLeave}
onClick={handleClick}
className={handleClassStyler('delivery)}
>
Delivery
</div>
<div
onMouseOver={handleOnMouseOver}
onMouseLeave={handleOnMouseLeave}
onClick={handleClick}
className={handlePickupClassStyler('pickup')}
>
Pick Up
</div>
</div>
);
}
我上面用的CSS是:
.delivery {
width: 100px;
height: 100px;
background-color: red;
border: solid black 5px;
margin: 5px;
}
.deliveryClicked {
width: 100px;
height: 100px;
background-color: blue;
border: solid black 5px;
margin: 5px;
}
.deliveryHovered {
width: 100px;
height: 100px;
background-color: green;
border: solid black 5px;
margin: 5px;
}
.pickup {
width: 100px;
height: 100px;
background-color: red;
border: solid black 5px;
margin: 5px;
}
.pickupClicked {
width: 100px;
height: 100px;
background-color: blue;
border: solid black 5px;
margin: 5px;
}
.pickupHovered {
width: 100px;
height: 100px;
background-color: green;
border: solid black 5px;
margin: 5px;
}
嗯,
在阅读了所有的输入(这对理清我的逻辑非常有帮助)之后,我有了一个想法并进行了一些重构:
但是,由于几乎接近解决方案,我仍然需要解决我的默认状态。我又被困住了。
默认状态应该是 Delivery,并且(按钮)也应该激活 CSS。
此外,当我添加 CSS .deliveryChoice:hover {} 时,它没有响应。我的猜测是,因为它是一个 child 组件,所以 header 没有响应,因为它没有读取内部按钮。
现在,它们都关闭了。
我的Header组件:
const Header = props => {
return (
<Fragment>
<header className={classes.header}>
<div className={classes.logo} onClick={reload}>
<div >
Foodzilla
</div>
</div>
<div className={classes.delivery}>
<DeliveryButton
className={classes.deliveryChoice}
/>
</div>
<div>
<div className={classes.deliveryAdress}>
Delivery to:
</div>
</div>
<div className={classes.deliveryTime}>
<div >
Choose time: Now
</div>
</div>
<HeaderCartButton onClick={props.onShowCart} />
</header>
<div className={classes['main-image']}>
<img src={mealsImg} />
</div>
</Fragment>
还有我的 DeliveryButton:
const deliveryChoice = [{ name: 'Delivery' }, { name: 'PickUp' }]
const DeliveryButton = () => {
const [active, setActive] = useState(false);
return deliveryChoice.map((data, k) => (
<div
key={k}
className={`deliveryChoice ${active === k ?
classes.deliveryAction : ''}`}
onClick={() => setActive(k)}
>
{data.name}
</div>
));
};
和 CSS 按钮:
.deliveryChoice {
}
.deliveryAction {
background-color: #ffffff;
border-color: #ffffff;
display: flex;
font-size: 13px;
justify-content: space-around;
width: 4rem;
height: 1.8rem;
cursor: pointer;
color: rgb(0, 0, 0);
align-items: center;
border-radius: 20px;
/* padding-left: 0.5rem; */
}
我正在尝试编写一个 useState() Hook,并可能添加 useEffect() 来解决两个按钮上的活动状态。 Delivery 按钮需要使用 CSS 更改激活第一个按钮交付,如果单击第二个按钮 PickUp,它应该更改 CSS UI 以保持活动状态。 是的,如果可能的话,我想使用 Hooks。
有什么办法可以这样完成吗?
const Header = props => {
const [isActive, setIsActive] = useState(false);
function changeButtons () {
setIsActive = (!isActive)
};
return (
<Fragment>
<header className={classes.header}>
<div className={classes.logo} onClick={reload}>
<div >
Foodzilla
</div>
</div>
<div className={classes.delivery}>
<div
className={isActive ? classes.deliveryAction : classes.deliveryChoice}
onChange={changeButtons}
>Delivery</div>
<div className={classes.or}>or</div>
<div
className={isActive ? classes.pickUpAction : classes.pickUpChoice}
onChange={changeButtons}
>Pick Up</div>
</div>
好的,所以我做了一个你想要做的模型(我想 :D)。这是工作解决方案的 link:https://codesandbox.io/s/quiet-mountain-68e10k?file=/src/styles.css:59-775.
代码也在下面。确实可以进行一些重构,但我想至少让您走上正确的道路。
快速总结: 蓝色被选中(激活时优先于悬停和默认)。 绿色悬停(在 div 之外时返回默认值)。 红色是默认值(如果未单击或悬停,则显示红色)。
import "./styles.css";
import React, { useState } from "react";
export default function App() {
const [isDeliveryClicked, setIsDeliveryClicked] = useState(false);
const [isPickupClicked, setIsPickupClicked] = useState(false);
const [isDeliveryHovered, setIsDeliveryHovered] = useState(false);
const [isPickupHovered, setIsPickupHovered] = useState(false);
const handleClick = (e) => {
if (e.target.className.includes("delivery")) {
setIsDeliveryClicked(true);
setIsDeliveryHovered(false);
if (isDeliveryClicked === true) {
setIsDeliveryClicked(false);
setIsDeliveryHovered(true)
}
} else if (e.target.className.includes("pickup")) {
setIsPickupClicked(true);
setIsPickupHovered(false);
if (isPickupClicked === true) {
setIsPickupClicked(false);
setIsPickupHovered(true)
}
}
};
const handleOnMouseOver = (e) => {
if (e.target.className.includes("delivery")) {
setIsDeliveryHovered(true);
} else if (e.target.className.includes("pickup")) {
setIsPickupHovered(true);
}
};
const handleOnMouseLeave = (e) => {
if (e.target.className.includes("delivery")) {
setIsDeliveryHovered(false);
} else if (e.target.className.includes("pickup")) {
setIsPickupHovered(false);
}
};
const handleClassStyler = (buttonType) => {
if (buttonType === 'delivery') {
if (isDeliveryClicked === true) {
return "deliveryClicked";
} else if (isDeliveryHovered === true && isDeliveryClicked === false) {
return "deliveryHovered";
} else if (isDeliveryClicked === false && isDeliveryHovered === false) {
return "delivery";
}
} else if (buttonType === 'pickup'){
if (isPickupClicked === true) {
return "pickupClicked";
} else if (isPickupHovered === true && isPickupClicked === false) {
return "pickupHovered";
} else if (isPickupClicked === false && isPickupHovered === false) {
return "pickup";
}
}
};
return (
<div className="App">
<div
onMouseOver={handleOnMouseOver}
onMouseLeave={handleOnMouseLeave}
onClick={handleClick}
className={handleClassStyler('delivery)}
>
Delivery
</div>
<div
onMouseOver={handleOnMouseOver}
onMouseLeave={handleOnMouseLeave}
onClick={handleClick}
className={handlePickupClassStyler('pickup')}
>
Pick Up
</div>
</div>
);
}
我上面用的CSS是:
.delivery {
width: 100px;
height: 100px;
background-color: red;
border: solid black 5px;
margin: 5px;
}
.deliveryClicked {
width: 100px;
height: 100px;
background-color: blue;
border: solid black 5px;
margin: 5px;
}
.deliveryHovered {
width: 100px;
height: 100px;
background-color: green;
border: solid black 5px;
margin: 5px;
}
.pickup {
width: 100px;
height: 100px;
background-color: red;
border: solid black 5px;
margin: 5px;
}
.pickupClicked {
width: 100px;
height: 100px;
background-color: blue;
border: solid black 5px;
margin: 5px;
}
.pickupHovered {
width: 100px;
height: 100px;
background-color: green;
border: solid black 5px;
margin: 5px;
}
嗯, 在阅读了所有的输入(这对理清我的逻辑非常有帮助)之后,我有了一个想法并进行了一些重构: 但是,由于几乎接近解决方案,我仍然需要解决我的默认状态。我又被困住了。 默认状态应该是 Delivery,并且(按钮)也应该激活 CSS。 此外,当我添加 CSS .deliveryChoice:hover {} 时,它没有响应。我的猜测是,因为它是一个 child 组件,所以 header 没有响应,因为它没有读取内部按钮。
现在,它们都关闭了。
我的Header组件:
const Header = props => {
return (
<Fragment>
<header className={classes.header}>
<div className={classes.logo} onClick={reload}>
<div >
Foodzilla
</div>
</div>
<div className={classes.delivery}>
<DeliveryButton
className={classes.deliveryChoice}
/>
</div>
<div>
<div className={classes.deliveryAdress}>
Delivery to:
</div>
</div>
<div className={classes.deliveryTime}>
<div >
Choose time: Now
</div>
</div>
<HeaderCartButton onClick={props.onShowCart} />
</header>
<div className={classes['main-image']}>
<img src={mealsImg} />
</div>
</Fragment>
还有我的 DeliveryButton:
const deliveryChoice = [{ name: 'Delivery' }, { name: 'PickUp' }]
const DeliveryButton = () => {
const [active, setActive] = useState(false);
return deliveryChoice.map((data, k) => (
<div
key={k}
className={`deliveryChoice ${active === k ?
classes.deliveryAction : ''}`}
onClick={() => setActive(k)}
>
{data.name}
</div>
));
};
和 CSS 按钮:
.deliveryChoice {
}
.deliveryAction {
background-color: #ffffff;
border-color: #ffffff;
display: flex;
font-size: 13px;
justify-content: space-around;
width: 4rem;
height: 1.8rem;
cursor: pointer;
color: rgb(0, 0, 0);
align-items: center;
border-radius: 20px;
/* padding-left: 0.5rem; */
}