728x90
반응형
목차
범용성이 좋은 modal component
import { useEffect, useRef } from "react";
import { createPortal } from "react-dom";
function Modal({ children, className = "", open, onClose }) {
const dialog = useRef();
useEffect(() => {
//참조값을 지정해 놓기
const modal = dialog.current;
if (open) {
modal.showModal();
}
return () => {
modal.close();
};
}, [open]);
return createPortal(
<dialog ref={dialog} className={`modal ${className}`} onClose={onClose}>
{children}
</dialog>,
document.getElementById("modal")
);
}
export default Modal;
컴포넌트 설명
- children과 className을 통해 css 및 컴포넌트의 활용성을 높였다.
- open이라는 상태를 전달함으로써 모달이 닫히고 열리는 것을 구현하였고 clear함수를 통해 닫히는 기능이 만들어지는 것을 가져가면 좋을 것 같다.
- createPortal을 이용해서 dom의 modal에 직접 연결해 주었다.
- onClose를 쓴 이유는 esc를 누르면 외부에서 modal은 닫히지만 state자체는 변경되지 않았기 때문에 다시 모달이 안열리는 경우를 막기 위해서이다.
modal ContextProvider
아래 코드는 이러한 모달을 이용한 컴포넌트들을 전역적으로 관리하기 위해 만든 contextProvider이다.
import { createContext, useState } from "react";
export const userProgressContext = createContext({
progress: "",
showCart: () => {},
hideCart: () => {},
showCheckout: () => {},
hideCheckout: () => {},
});
export function UserProgressContextProvider({ children }) {
const [userProgress, setUserProgress] = useState("");
function showCart() {
setUserProgress("cart");
}
function hideCart() {
setUserProgress("");
}
function showCheckout() {
setUserProgress("checkout");
}
function hideCheckout() {
setUserProgress("");
}
const userProgressCtx = {
progress: userProgress,
showCart,
hideCart,
showCheckout,
hideCheckout,
};
return (
<userProgressContext.Provider value={userProgressCtx}>
{children}
</userProgressContext.Provider>
);
}
전역적으로 설정한 모달 컴포넌트의 활용
import { useContext } from "react";
import Button from "./UI/Button";
import { userProgressContext } from "./store/UserProgressContext";
import Modal from "./Modal";
import CartItem from "./CartItem";
function Cart() {
const userProgressCtx = useContext(userProgressContext);
function handleHideCart() {
userProgressCtx.hideCart();
}
return (
<Modal
className="cart"
open={userProgressCtx.progress === "cart"}
onClose={userProgressCtx.progress === "cart" ? handleHideCart : null}
>
<Button onClick={handleCheckout}>go to Checkout</Button>
</Modal>
);
}
export default Cart;
위 코드에서의 주의사항이다.
onClose={userProgressCtx.progress === "cart" ? handleHideCart : null}
이렇게 코드를 짠 이유는 userProgressCtx.progress가 checkout일 때는 onClose의 기능을 비활성화해서 checkout이 열리게끔 만들어야하기 때문이다.
반응형
'코딩 정보 > React' 카테고리의 다른 글
[React] 리덕스의 개념과 활용 방법에 대해 알아보자 (0) | 2024.08.11 |
---|---|
[React] useEffect와 관련되어 순차적으로 에러 핸들링 해보기 (0) | 2024.08.10 |
[React] useEffect의 실행 시점에 대해 알아보자 (0) | 2024.08.09 |
[React] form 양식 다루기 (사용자 유효성 검사) (0) | 2024.08.02 |
[React] Custom Hook에 대해 알아보자 (0) | 2024.07.31 |