프로젝트 진행 중, 로그인 후에 에러 메세지를 보여줄 모달창이 필요해졌다.
다른 프로젝트에서도 최대한 재사용이 가능하도록 만들어 보기로 했다.
우선 관련된 모든 파일은 한 폴더 내에서 작업하기로 함!
메인파일 : PopupJs.js
상세팝업종류 : component > PopupType.js
스타일 : style.js (styled-components)
hook : hook > usePopup.js (팝업 열기,닫기)
recoil : state > popupState.js
- index.js 나 App.js 등 최상단 파일에서 PopupJs.js 컴포넌트를 넣어준다.
- 팝업이 필요한 파일에서 hook을 불러온다.
- 팝업창이 열리도록 addPopup() 함수에 속성 정보를 넘겨준다.
✨중요 : type에 따라 팝업 종류 결정
- type에 따라 해당 팝업 스타일 컴포넌트를 리턴한다. (중첩 팝업 가능)
const filterPopup = (props, index) => { const { data: { type }, } = props; if (type === 'basic') { return <BasicPopup key={index} {...props} />; } if (type === 'towBtn') { return <TowBtnPopup key={index} {...props} />; } if (type === 'fileUpload') { return <FileUploadPopup key={index} {...props} />; } if (type === 'fileExport') { return <FileExportPopup key={index} {...props} />; } if (type === 'boringAdd') { return <BoringAddPopup key={index} {...props} />; } return; }; return <>{popupList.map((props, index) => filterPopup(props, index))}</>; } export default PopupJs;
- 대표적으로
<BasicPopup />
형태// 기본 팝업 - 단순 창 닫기 export function BasicPopup({ data: { title = '알림', text = '', confirm } }) { const { removeCurrentPopup } = usePopup(); return ( <Style.Dimmed> <Style.Wrap> <Style.Box> <div className="title"> {title} <button className="closeBtn" onClick={removeCurrentPopup}></button> </div> <div className="border"></div> <div className="message">{text}</div> <div className="btnWrap"> <button className="confirm" onClick={removeCurrentPopup}> 확인 </button> </div> </Style.Box> </Style.Wrap> </Style.Dimmed> ); }
- hook > usePopup.js
export default function usePopup() { const [popupList, setPopupList] = useRecoilState(popupState); // 보여줄 팝업 추가 - 중첩 가능 const addPopup = useCallback(({ key, data }) => { console.log('addpopup!'); setPopupList((prev) => { let newModalList = [...prev]; newModalList.push({ key, data }); // 추가 return newModalList; }); }, []); // 닫기 이벤트 const removeCurrentPopup = useCallback(() => { console.log('removeCurrentPopup!'); setPopupList((prev) => { let newModalList = [...prev]; newModalList.pop(); // 마지막 항목 삭제 return newModalList; }); }, []); return { addPopup, removeCurrentPopup, }; }