fix: add null checks for document and firebase messaging to prevent SSR errors

Added defensive programming by adding null checks for document object before accessing its properties and methods across multiple components (MultiSelect, ConfirmationModal, Dropdown, Modal). Also implemented lazy initialization for Firebase messaging to prevent SSR-related errors and ensure messaging is only initialized on the client side. These changes improve server-side rendering compatibility and prevent potential runtime errors.
This commit is contained in:
AmirReza Jamali
2025-11-15 12:22:30 +03:30
parent 5e60a292f5
commit 1d1027fab4
6 changed files with 50 additions and 17 deletions
+2 -1
View File
@@ -130,8 +130,9 @@ function MultiSelect<T extends FieldValues>({
return;
setShow(false);
};
document?.addEventListener("click", clickHandler);
return () => document.removeEventListener("click", clickHandler);
return () => document?.removeEventListener("click", clickHandler);
}, [show]);
return (
+9 -6
View File
@@ -8,12 +8,15 @@ import { toast } from "react-toastify";
const Notification = ({ children }: PropsWithChildren) => {
useEffect(() => {
onMessage(messaging, (payload) => {
console.log("Message received. ", payload);
if (payload.notification) {
toast.success(payload.notification.title ?? "New Notification");
}
});
const messagingInstance = messaging();
if (messagingInstance) {
onMessage(messagingInstance, (payload) => {
console.log("Message received. ", payload);
if (payload.notification) {
toast.success(payload.notification.title ?? "New Notification");
}
});
}
}, []);
return <>{children}</>;
+3 -3
View File
@@ -54,12 +54,12 @@ const ConfirmationModal: React.FC<ConfirmationModalProps> = (props) => {
if (isOpen) {
document?.addEventListener("keydown", handleEscape);
document.body.style.overflow = "hidden";
if (document) document.body.style.overflow = "hidden";
}
return () => {
document.removeEventListener("keydown", handleEscape);
document.body.style.overflow = "unset";
document?.removeEventListener("keydown", handleEscape);
if (document) document.body.style.overflow = "unset";
};
}, [isOpen, onCancel]);
+2 -2
View File
@@ -46,9 +46,9 @@ export function Dropdown({ children, isOpen, setIsOpen }: DropdownProps) {
if (isOpen) {
triggerRef.current = document.activeElement as HTMLElement;
document.body.style.pointerEvents = "none";
if (document) document.body.style.pointerEvents = "none";
} else {
document.body.style.removeProperty("pointer-events");
if (document) document.body.style.removeProperty("pointer-events");
setTimeout(() => {
triggerRef.current?.focus();
+3 -3
View File
@@ -33,13 +33,13 @@ const Modal: React.FC<ModalProps> = ({
useEffect(() => {
if (isOpen) {
document.body.style.overflow = "hidden";
if (document) document.body.style.overflow = "hidden";
} else {
document.body.style.overflow = "unset";
if (document) document.body.style.overflow = "unset";
}
return () => {
document.body.style.overflow = "unset";
if (document) document.body.style.overflow = "unset";
};
}, [isOpen]);