-
React Component 가변적으로 생성/추가하기, 제거하기 (Alert 가변 생성 예시 포함)DEV/react 2024. 2. 19. 11:00
* 컴포넌트 동적으로 생성/추가(가변적으로 생성)하는 코드만 필요한 경우 앞 Alert 코드는 넘어가도록 하자.
회원가입 및 로그인 기능을 구현하다 보니 로그인, 회원가입에 대한 Alert이 필요했다.
(성공, 실패 여부. 에러 및 실패에 대한 사유 등 알림을 띄워주기 위해 필요.)
Alert Component를 하나 만들고 로그인 및 회원가입 API Response에 따라 Alert을 가변적으로 생성하려고 한다.
우선 Alert 코드를 다음과 같이 생성하였다.
Alert.js
import style from '../../style/component/Alert.module.css' import React, { useRef, useEffect } from 'react'; /** * [Alert] * @param alertType {String} "success", "warning", "error" 중 택 1, 지정하지 않거나 다른 값을 넣는 경우 일반 테마 적용됨 * @param contents {String} Alert 내용 * @param duration {Number} Alert 자동 종료 시간(Sec), 값이 없는 경우 종료하지 않음 * @returns {Element} */ const Alert = ({alertType, contents, duration}) => { // Alert style을 가변적으로 지정하기 위해 사용 let styleType; // Dom 선택을 위해 Ref 생성 const alertRef = useRef(null); // Alert style 지정 styleType = `${style.alertContainer} `; if(alertType === 'success') { styleType = styleType + `${style.success}`; } else if(alertType === 'warning') { styleType = styleType + `${style.warning}`; } else if(alertType === 'error') { styleType = styleType + `${style.error}`; } else { styleType = styleType + `${style.normal}`; } /** * [Alert 제거] * - Alert Component에서 parameter로 duration을 받은 경우 duration 이후 자동 종료됨. * - duration에 상관없이 x 아이콘을 눌렀을 때 또한 종료됨. */ const closeAlert = () => { const elementToRemove = alertRef.current; // duration 이전에 alert 종료 버튼을 먼저 누르는 경우 해당 노드가 없어 에러가 발생하여 조건문 추가 if (elementToRemove && elementToRemove.parentNode) { elementToRemove.parentNode.removeChild(elementToRemove); } }; useEffect(() => { if (duration) { /** * setTimeout으로 duration 타임 이후 해당 alert 제거하는 함수 호출 * duration : 자동 종료 시간, 단위 Sec로 자동 변경 */ const timeoutId = setTimeout(() => { closeAlert(); }, duration * 1000); return () => clearTimeout(timeoutId); } }, [duration]); return ( <div className={styleType} ref={alertRef}> {/* Contents */} <div> <label> {contents} </label> </div> {/* X button */} <div onClick={closeAlert}> <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" focusable="false" viewBox="0 0 12 12" aria-hidden="true"> <path stroke="currentColor" strokeLinecap="round" d="M3 9l6-6m0 6L3 3"></path> </svg> </div> </div> ); }; export default Alert;
Alert.module.css
.alertContainer { display: flex; align-items: center; justify-content: space-between; padding-inline: 10px; padding-block: 8px; box-sizing: border-box; width: 100%; border-radius: 8px; margin-bottom: 5px; } .success { background-color: rgb(237, 248, 244); border: 1px solid rgb(89 184 147); color: rgb(24, 97, 70); } .warning { background-color: rgb(255, 247, 237); border: 1px solid rgb(254, 214, 168); color: rgb(173, 89, 24); } .error { background-color: rgb(255, 240, 241); border: 1px solid rgb(245, 181, 186); color: rgb(140, 35, 44); } .normal { background-color: rgb(248, 249, 249); border: 1px solid rgb(216, 220, 222); color: rgb(104, 115, 125) }
그리고 해당 Alert Component를 동적으로 생성이 필요한 곳으로 이동하여 다음과 같이 사용해보자.
LoginPage.js (나는 여기서 Alert을 생성하고자 함)
// ... LoginPage 코드 생략 // Alert const [alerts, setAlerts] = useState([]); const addAlert = (alertType, contents, duration) => { const newAlert = <Alert key={alerts.length} alertType={alertType} contents={contents} duration={duration} />; setAlerts([...alerts, newAlert]); } // ...LoginPage 코드 생략 // API 호출 후 Response를 받는 부분... addAlert('warning', response.data.message, 3); // API 예외처리 부분... } catch(error) { addAlert('error', error, 3); } // ... LoginPage 코드 생략 return ( <div className={style.backgroundContainer}> {/* alert을 넣어 줄 Container */} <div className={style.alertStackContainer}> {alerts.map((alert, index) => ( <div key={index}>{alert}</div> ))} </div> // ... 이후 코드 생략
LoginPage.module.css
/* 그 외 css 생략 */ .alertStackContainer { position: absolute; right: 10px; top: 10px; display: flex; flex-direction: column; width: 500px; border-radius: 10px; z-index: 1; }
useState로 alerts 배열을 생성하고 addAlert 함수를 통해 Alert Component를 저장한다.
LoginPage를 구성하고 return해 주는 부분에 Alert을 띄워줄 공간을 만들어 두었다. (alertStackContainer)
{alerts.map((alert, index) => ( <div key={index}>{alert}</div> ))}
위와 같이 useState로 관리되는 alerts를 출력해 준다.
useState에 대한 개념이 부족하다면 하단 게시물을 참고하자.
https://seokbong.tistory.com/243
관련 게시물
https://seokbong.tistory.com/253
'DEV > react' 카테고리의 다른 글
React 전역 변수를 사용하자 (부모-자식 컴포넌트 접근, Context) (0) 2024.02.21 React App build 명령어 (0) 2024.02.20 React Javascript 키 입력 이벤트 "onKeyPress is deprecated..." onKeyDown, onKeyUp을 쓰자. (0) 2024.02.16 React Hooks 간단 정리 (0) 2024.01.24 React 시작하기 9. Array 항목 추가 (1) 2024.01.05