I'm working on a shopping cart application using ReactJS and Context-API, so far, I achieved this:
- load my products from Firebase
- Add product to the cart
The next step is to display the cart's content loading a modal form when the user clicks on the properly icon, but in this part I'm getting this error:
Target container is not a DOM Element
This is the code from FoodOrder, which is one of the most important:
import React, { useState } from "react";
import Header from "./Layout/Header";
import Meals from "./Meals/Meals";
import Cart from "./Cart/Cart";
import CartProvider from "./store/CartProvider";
const FoodOrder = () => {
const [cartIsShown, setCartIsShown] = useState(false);
const showCartHandler = () => {
setCartIsShown(true);
};
const hideCartHandler = () => {
setCartIsShown(false);
};
return (
<CartProvider>
{cartIsShown && <Cart onClose={hideCartHandler} />}
<Header onShowCart={showCartHandler} />
<main>
<Meals />
</main>
</CartProvider>
);
};
export default FoodOrder;
Header.js component is like a container which pass the props to HeaderCartButton, the bellow code is from Header.js:
import React, { Fragment } from "react";
import HeaderCartButton from "./HeaderCartButton";
import mealsImage from "../assets/banner.jpg";
import classes from "./Header.module.css";
const Header = (props) => {
return (
<Fragment>
<header className={classes.header}>
<h1>Let's order pupusas</h1>
<HeaderCartButton onClick={props.onShowCart} />
</header>
<div className={classes['main-image']}>
<img src={mealsImage} alt="all you can eat pupusas" />
</div>
</Fragment>
);
};
export default Header;
And this is the code from HeaderCartButton.js:
import { useContext, useEffect, useState } from "react";
import CartIcon from "../Cart/CartIcon";
import CartContext from "../store/cart-context";
import classes from "./HeaderCartButton.module.css";
const HeaderCartButton = (props) => {
const [btnIsHighlighted, setBtnIsHighlighted] = useState(false);
const cartCtx = useContext(CartContext);
const { items } = cartCtx;
const numberOfCartItems = items.reduce((curNumber, item) => {
return curNumber + item.amount;
}, 0);
const btnClasses = `${classes.button} ${
btnIsHighlighted ? classes.bump : ""
}`;
useEffect(() => {
if(items.length === 0){
return;
}
setBtnIsHighlighted(true);
const timer = setTimeout(() => {
setBtnIsHighlighted(false);
}, 300);
return() => {
clearTimeout(timer);
}
}, [items]);
return(
<button className={btnClasses} onClick={props.onClick}>
<span className={classes.icon}>
<CartIcon />
</span>
<span>Your Shopping</span>
<span className={classes.badge}>{numberOfCartItems}</span>
</button>
);
}
export default HeaderCartButton;
Finally, this is the source code from the Modal.js component:
import React from "react";
import ReactDOM from "react-dom";
import classes from "./Modal.module.css";
const Backdrop = (props) => {
return <div className={classes.Backdrop} onClick={props.onClose}></div>;
};
const ModalOverLay = (props) => {
return (
<div className={classes.modal}>
<div className={classes.content}>{props.children}</div>
</div>
);
};
const portalElement = document.getElementById("overlays");
const Modal = (props) => {
return (
<React.Fragment>
{ReactDOM.createPortal(
<Backdrop onClose={props.onClose} />,
portalElement
)}
{ReactDOM.createPortal(
<ModalOverLay>{props.children}</ModalOverLay>,
portalElement
)}
</React.Fragment>
);
};
export default Modal;
As a final comment I'm not getting the error neither in the main web browser nor in my vscode console, I had to check the devtools to figure out what is going on.
So, any hints how to debug this error? what am I missing?
Thanks a lot
I believe your problem is this part:
By doing this you're essentially not rendering the
Cart
component at all ifcartIsShow
is false.It would be better to implement it this way:
And then handle the rendering inside the
Cart
component using that value so that you can appropriately make use of the lifecycle functionality inside theCart
component (instead of avoid that all completely)