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; */
}