I have a react CheckProfileModal component that is supposed to render a modal to a portal div I created in the index.html. My Home.jsx handles the UseEffect hook that checks the firestore database and renders the modal if certain conditions are true. I get the uncaught error even though my portal div is present in my index.html.
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React</title>
<script type="module" crossorigin src="/assets/index-5dfa2cb2.js"></script>
<link rel="stylesheet" href="/assets/index-c1e7090c.css" />
</head>
<body>
<div id="root"></div>
<div id="portal"></div>
</body>
</html>
These are the other components: CheckProfileModal .jsx
import React from "react";
import ReactDOM from "react-dom";
import { Backdrop, Box, Fade, Modal, Typography } from "@mui/material";
import styles from "../../src/assets/Styles/ModalStyles.module.css";
export const CheckProfileModal = () => {
const [open, setOpen] = React.useState(false);
const handleClose = () => setOpen(false);
// handleopen to be triggered by useEffect
return ReactDOM.createPortal(
<>
<Modal
aria-labelledby="transition-modal-title"
aria-describedby="transition-modal-description"
open={open}
onClose={handleClose}
closeAfterTransition
slots={{ backdrop: Backdrop }}
slotProps={{
backdrop: {
timeout: 500,
},
}}
>
<Fade in={open}>
<Box sx={styles}>
<Typography id="transition-modal-title" variant="h6" component="h2">
Text in a modal
</Typography>
<Typography id="transition-modal-description" sx={{ mt: 2 }}>
Duis mollis, est non commodo luctus, nisi erat porttitor ligula.
</Typography>
</Box>
</Fade>
</Modal>
</>,
document.querySelector("#portal")
);
};
Home.jsx
import { IconButton, Typography } from "@mui/material";
import { getDoc, doc } from "firebase/firestore";
import React, { useEffect, useState } from "react";
import { db } from "../utils/firebaseConfig";
import "@fontsource/lexend";
import "@fontsource/lexend/500.css";
import "@fontsource/lexend/100.css";
import styles from ".././assets/Styles/AddictionsOptiosStyles.module.css";
import classNames from "classnames";
import Alcohol from ".././assets/images/addictions/alcohol.png";
import { nanoid } from "nanoid";
import { CheckProfileModal } from "../Modals/CheckProfileModal";
export const Home = () => {
const userCredentials = JSON.parse(localStorage.getItem("userCredentials"));
const [firstName, setfirstName] = useState("");
const [modal, setModal] = useState(false);
useEffect(() => {
const fetchData = async () => {
try {
const userSnap = await getDoc(doc(db, "users", userCredentials));
if (
!userSnap.data().firstName ||
!userSnap.data().lastName ||
!userSnap.data().mobile
) {
setModal(true);
} else if (
userSnap.data().firstName ||
userSnap.data().lastName ||
userSnap.data().mobile
) {
setfirstName(userSnap.data().firstName);
}
} catch (error) {
console.log("Error fetching user data:", error);
}
};
fetchData();
}, [userCredentials]);
return (
<>
<div className="pl-5">
<div className={classNames("pt-10", styles.homeHeader)}>
<div className={styles["headerName"]}>
<Typography
sx={{
fontFamily: "Lexend",
fontSize: "20px",
fontWeight: 500,
lineHeight: "22px",
letterSpacing: "0.005em",
textAlign: "left",
}}
>
Hello, {firstName}
</Typography>
<Typography
sx={{
fontFamily: "Lexend",
fontSize: "15px",
fontWeight: 100,
lineHeight: "22px",
letterSpacing: "0.005em",
textAlign: "left",
paddingTop: "10px",
}}
>
How are you doing today?
</Typography>
</div>
<div key={nanoid()} className={styles["profile-image"]}>
<IconButton>
<div>
<img src={Alcohol} />
</div>
</IconButton>
</div>
</div>
</div>
{modal && <CheckProfileModal />}
</>
);
};