How to pass state from a button to another component

Viewed 523

When I click on a button, I am adding a product to the cart but I also want to set the state of a side drawer to true so it appears. This is working but trying to pass that state to the component so that when I click on close is giving me trouble. Here are basically all the moving parts:

const [isOpen, setIsOpen] = useState(false);

const addToCartHandler = async (id) => {
 setIsOpen(true);
 // add to cart logic here
}

<CartDrawer toggleOpen={isOpen} />
<Button
  variant="primary"
  onClick={() => addToCartHandler(id)}
>
  Add to Cart
</Button>

This is working fine. I click on add to cart, it adds to cart and my modal shows up as expected.

The modal is basically component and I am receiving toggleOpen as props. Here is the CartDrawer component

const CartDrawer = (props) => {
  const [isOpen, setIsOpen] = useState(false);

  const closeNavHandler = () => {
    setIsOpen(false);
  };

  return (
    <div
      id="mySidenav"
      className={props.toggleOpen ? "sidenav open" : "sidenav"}
    >
      <a
        className="closebtn"
        onClick={closeNavHandler}
      >
        &times;
      </a>
    </div>
  );
};

export default CartDrawer;

I know this is wrong but I can't figure out how to update the state here correctly to close it.

2 Answers

Just control everything from the parent. The cartDrawer only needs to receive a ìsOpen prop to know its state. Don't write another state in it.

A component like this should be stupid. It receives informations, and display them. Don't spill the logic all over your components. Just have a single source of truth.

// Main
const [isOpen, setIsOpen] = useState(false);

const addToCartHandler = async (id) => {
 setIsOpen(true);
 // add to cart logic here
}

<CartDrawer isOpen={isOpen} onClose={()=> setIsOpen(false)}/>
<Button
  variant="primary"
  onClick={() => addToCartHandler(id)}
>
  Add to Cart
</Button>


// CartDrawer
const CartDrawer = ({isOpen, onClose}) => {

  return (
    <div
      id="mySidenav"
      className={isOpen ? "sidenav open" : "sidenav"}
    >
      <a
        className="closebtn"
        onClick={onClose}
      >
        &times;
      </a>
    </div>
  );
};

export default CartDrawer;

I think that's what you want?

const [isOpen, setIsOpen] = useState(false);

const addToCartHandler = async (id) => {
 setIsOpen(true);
 // add to cart logic here
}

const toggleOpenDrawer = (val) => {
  setIsOpen(val);
}

<CartDrawer toggleOpenDrawer={toggleOpenDrawer} toggleOpen={isOpen} />
<Button
  variant="primary"
  onClick={() => addToCartHandler(id)}
>
  Add to Cart
</Button>
const CartDrawer = (props) => {
  const { toggleOpenDrawer } = props
  return (
    <div
      id="mySidenav"
      className={props.toggleOpen ? "sidenav open" : "sidenav"}
    >
      <a
        className="closebtn"
        onClick={toggleOpenDrawer(!props.toggleOpen)}
      >
        &times;
      </a>
    </div>
  );
};

export default CartDrawer;
Related