'Switch active buttons using useState and useEffect Hooks for Buttons in JavaScript/React?

I am trying to write a useState() Hook, and perhaps add useEffect() to solve active state on two buttons. It is Delivery buttons that needs the first button-delivery to be active using CSS change, and if clicked on second button, PickUp, it should change CSS UI to stay active. And yes if it is anyhow possible i want to use Hooks.

Is there any possible way to have it done on this way?

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>


Solution 1:[1]

Okay, so I did a mockup of what you are trying to do (I think :D). Here is a link to the working solution: https://codesandbox.io/s/quiet-mountain-68e10k?file=/src/styles.css:59-775.

The code is also below. There is definitely some refactoring that can be done, but I wanted to at least get you started on the right path.

Quick Summary: Blue is Cicked (takes precedence over hover and default when active). Green is Hovered (goes back to default when outside the div). Red is Default (if not clicked or hovered, show red).

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>
  );
}

The CSS I used for above is:

.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;
}

Solution 2:[2]

Well, After reading all the input (which was incredibly helpful to get my logic straight) i have come with an idea and some refactoring: However, as almost close to a solution i still need to solve my default state. And i am stuck again. Default state should be Delivery, and the (button) should have active CSS as well. Also, when i add CSS .deliveryChoice:hover {} it does not respond. My guess is that, as it is a child component the header don't respond as it reads no inside buttons.

Right now, they are both off.

My Header component:

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>

And my 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>
));
};

And CSS for the Button:

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

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Matija Kosmac