I am creating one Alert component. For styling I am using Style-components. For typescript I put props any. My alert component works fine. And it Looks like this. As soon as I add interface props I am getting bunch of errors. first error is Cannot invoke an object which is possibly 'undefined'.
This is the parent component where I am using my Alert component.
<button
style={{ color: "red" }}
onClick={() =>
Alert({
id: "sign-in-fail-alert",
title: "Good Job!",
alertType: "success",
onConfirm: () => setValue("click"),
children: <div>You clicked the button! </div>
})
}
>
Show alert!
</button>
This is my Alert component. Inside the Alert component I created the Modal then I passed it to the Alert variable. My alert variable's interface works fine. I am getting error from my Modal interface.
import React from "react";
import ReactDOM from "react-dom";
import styled from "styled-components";
import { Button } from "components/buttons";
import { CloseIcon } from "assets/icons";
export const Container = styled.div`
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #000000e0;
position: fixed;
z-index: 3;
display: flex;
flexdirection: row;
justifycontent: center;
alignitems: center;
aligncontent: center;
`;
export const ModalOverlay = styled.div`
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.8);
cursor: pointer;
z-index: 1;
`;
export const ModalClose = styled.button`
position: absolute;
top: 20px;
right: 20px;
transition: transform 250ms ease-in-out;
transform-origin: 50% 50%;
&:hover {
transform: rotate(180deg);
}
`;
export const IconContainer = styled.div`
position: relative;
z-index: 2;
top: 6%;
left: 47%;
box-sizing: content-box;
border-radius: 50%;
`;
export const ModalBox = styled.div`
position: relative;
width: 40%;
padding: 1.25em;
border: none;
margin: 10% 10% 10% 25%;
box-sizing: border-box;
border-radius: 10px;
background-color: white;
cursor: auto;
z-index: 2;
`;
export const Confirm = styled(Button)`
position: relative;
top: 100%;
left: 50%;
`;
export const Title = styled.h1`
position: relative;
top: 40%;
font-size: 50px;
text-align: center;
color: ${({ theme }) => theme.textColor};
`;
export const Children = styled.h1`
position: relative;
top: 40%;
font-size: 20px;
text-align: center;
color: ${({ theme }) => theme.textColor};
`;
export interface IModal {
title: string;
onClose?: () => void;
onCancel?: () => void;
onConfirm?: () => void;
children?: JSX.Element | string;
icon?: JSX.Element;
alertType?: "success" | "error" | "warning" | "info" | "question";
}
export const Modal = ({
title,
children,
onClose,
onCancel,
onConfirm,
icon,
alertType
}: IModal) => { // If I type any it works fine
const handleCancel = () => {
onCancel(); //Getting error from here
onClose(); //Getting error from here
};
const handleConfirm = () => {
onConfirm(); //Getting error from here
onClose(); //Getting error from here
};
return (
<Container>
<ModalOverlay onClick={onClose} />
<ModalBox>
<ModalClose onClick={onClose}>
<CloseIcon />
</ModalClose>
<Title>{title}</Title>
<IconContainer>
{icon ? (
icon
) : alertType === "success" ? (
<CloseIcon />
) : alertType === "error" ? (
<p>error</p>
) : alertType === "warning" ? (
<p>warning</p>
) : alertType === "info" ? (
<p>info</p>
) : alertType === "question" ? (
<p>question</p>
) : null}
</IconContainer>
<Children> {children}</Children>
{onCancel && <Button onClick={handleCancel}>Cancel</Button>}
{onConfirm && <Confirm onClick={handleConfirm}>Confirm</Confirm>}
</ModalBox>
</Container>
);
};
export interface IAlert {
title: string;
children?: JSX.Element | string;
id: string;
alertType: string;
onCancel?: () => void;
onConfirm?: () => void;
}
export const Alert = ({
title,
children,
id,
alertType,
onCancel,
onConfirm
}: IAlert) => {
// search the DOM for an element with the same ID and remove it
const removeElement = () => document.getElementById(id)?.remove();
const createElement = () => {
const container = document.createElement(`div`);
container.setAttribute(`class`, "alert");
container.setAttribute(`id`, id);
document.body.appendChild(container);
ReactDOM.render(
<Modal
title={title}
alertType={alertType}
onCancel={onCancel}
onConfirm={onConfirm}
onClose={removeElement}
>
{children}
</Modal>,
container
);
};
return createElement();
};
if (onCancel) { onCancel(); }- Roberto ZvjerkovićonCancel && onCancel();. But used your logic. 👏🏾 - KrisnaalertType?: "success" | "error" | "warning" | "info" | "question";andalertType: string;are not matching. - Roberto Zvjerković