리액트 모달 팝업2
본문
모달 작동 방식의 대한 이해도가 조금 생겼습니다.
그런데 제가 구현하고자 하는 것은 예를 들면
main.jsx 에 모달버튼이 있고
import React, { useState } from "react";
function Main() {
// 상태 관리를 위한 useState 훅
const [open, setOpen] = useState(false);
return (
<div className="container">
<div className="visual">
<div className="txt">
<h1>메인 비주얼</h1>
<p>메인 비주얼 서브 텍스트 입니다. 메인 비주얼 서브 텍스트 입니다.</p>
</div>
</div>
<div className="inner">
<section className="section1">
<ul>
<li><button onClick={() => setOpen(true)}>모달1 테스트</button></li>
<li><button onClick={() => setOpen(true)}>모달2 테스트</button></li>
<li><button onClick={() => setOpen(true)}>모달3 테스트</button></li>
</ul>
</section>
</div>
</div>
);
}
export default Main;
app.jsx 에 모달 출력 부분이 있는데 main.jsx 에서 모달버튼을 클릭하면 app.jsx 에 모달 출력부분을
동작시켜야 하지 않나요? 해당 위치에서만 모달을 열 수 있다면 모달이 많아지면 관리가 불가능할거 같아서 app.jsx 에 모든 모달 출력 부분을 다 모아놓고 작동시킬려고 하다보니...
import 'assets/css/common.css';
import 'assets/css/style.css';
import { Routes, Route } from 'react-router-dom';
import Layout from 'layout/layout';
import Main from 'page/main';
import Sub01 from 'page/sub01';
import Sub02 from 'page/sub02';
import Sub03 from 'page/sub03';
// 모달
import React, { useState } from "react";
import { ModalPortal } from "component/modalPortal";
import { Modal_1 } from "component/modal";
import { Modal_2 } from "component/modal";
import { Modal_3 } from "component/modal";
function App() {
// 상태 관리를 위한 useState 훅
const [open, setOpen] = useState(false);
return (
<div>
<Routes>
<Route element= {<Layout />}>
<Route path="/" element={<Main />} />
<Route path="sub01" element={<Sub01 />} />
<Route path="sub02" element={<Sub02 />} />
<Route path="sub03" element={<Sub03 />} />
</Route>
</Routes>
<ModalPortal>
<Modal_1 isOpen={open} onClose={() => setOpen(false)}>
{/* children 영역 */}
<div className='modal_body'>
<h2>모달 1 타이틀</h2>
<p>이 항목을 삭제하시겠습니까?</p>
<div className='modal_footer'>
<button>삭제</button>
<button onClick={() => setOpen(false)}>
취소
</button>
</div>
</div>
</Modal_1>
<Modal_2 isOpen={open} onClose={() => setOpen(false)}>
{/* children 영역 */}
<div className='modal_body'>
<h2>모달 2 타이틀</h2>
<p>이 항목을 삭제하시겠습니까?</p>
<div className='modal_footer'>
<button>삭제</button>
<button onClick={() => setOpen(false)}>
취소
</button>
</div>
</div>
</Modal_2>
<Modal_3 isOpen={open} onClose={() => setOpen(false)}>
{/* children 영역 */}
<div className='modal_body'>
<h2>모달 3 타이틀</h2>
<p>이 항목을 삭제하시겠습니까?</p>
<div className='modal_footer'>
<button>삭제</button>
<button onClick={() => setOpen(false)}>
취소
</button>
</div>
</div>
</Modal_3>
</ModalPortal>
</div>
);
}
export default App;
modal.jsx
import React from "react";
export const Modal_1 = ({ isOpen, onClose, children }) => {
// 만약 isOpen이 false이면 null을 반환하여 모달을 렌더링하지 않음
if (!isOpen) return null;
return (
<div onClick={onClose} className="modal_container">
<div onClick={(e) => e.stopPropagation()} className="modal_content">
<button onClick={onClose} className="modal-close">닫기</button>
{children}
</div>
</div>
);
};
export const Modal_2= ({ isOpen, onClose, children }) => {
// 만약 isOpen이 false이면 null을 반환하여 모달을 렌더링하지 않음
if (!isOpen) return null;
return (
<div onClick={onClose} className="modal_container">
<div onClick={(e) => e.stopPropagation()} className="modal_content">
<button onClick={onClose} className="modal-close">닫기</button>
{children}
</div>
</div>
);
};
export const Modal_3= ({ isOpen, onClose, children }) => {
// 만약 isOpen이 false이면 null을 반환하여 모달을 렌더링하지 않음
if (!isOpen) return null;
return (
<div onClick={onClose} className="modal_container">
<div onClick={(e) => e.stopPropagation()} className="modal_content">
<button onClick={onClose} className="modal-close">닫기</button>
{children}
</div>
</div>
);
};
결론 : app.jsx 에 버튼 + 모달출력영역이 같이 있으면 잘 열리는데 실제 개발시 모달 버튼은 어디 있을지 모른다는거니까요..
modal.jsx 모달 껍데기
app.jsx 모달 출력 부분(모달 내용)
이런 구조인거 같은데 제가 이해한바로는 ㅎㅎ;;
맞는지 모르겠네요.
아무튼 모달들을 app.jsx 에 네이밍 다르게 처리해서 다 정리해놓고
다른 페이지에서 클릭시 해당 네이밍에 모달 열 수는 없나요..?
일반 퍼블에서는 뭐.. 제이쿼리로 data-id 값으로 열듯이 ㅎㅎ;;
!-->!-->!-->
답변 4
1. 일단 저렇게 하면 안좋은 습관을 배우시게 됩니다.
- 만약 모달이 500개면 컴포넌트 500개 만들건 아니잖아요?
- 따라서 하나의 모달 컴포넌트로 모든걸 제어 해야 합니다
2. main.jsx 에서 그냥 제어 하시거나 / app.jsx 에서 버튼 관리하시면 됩니다.
다음 코드 참조 하세요
import './App.css';
import Modal from './components/modal';
import { useState } from 'react';
function App() {
const [isOpen, setIsOpen] = useState([false, false, false]);
const handleModal = (index) => {
setIsOpen(prevState => {
const newState = [...prevState];
newState[index] = !newState[index];
return newState;
});
};
return (
<>
{isOpen.map((isModalOpen, index) => (
<div key={index}>
<button onClick={() => handleModal(index)}>Open Modal</button>
<Modal isOpen={isModalOpen} onClose={() => handleModal(index)}>
<h1>Modal Title {index + 1}</h1>
<p>Modal Content</p>
</Modal>
</div>
))}
</>
);
}
export default App;
위 코드는 App.js 인데 main.jsx 파일에서 제어하시던 그건 질문자님이 편하신데로 하시면 됩니다.
반복문을 통해 각각의 배열의 모달창 상태를 관리합니다.
이렇게 이해하시면 됩니다.
똑같은 애들을 여러번 만드는데..이게 맞는걸까?
- 1번만 만드시면 됩니다.
- 특히 나도 모르게 xxx_1 / xxx_2 / xxx_3 이렇게 하고 있다면, 100%입니다.
똑같은 애들을 여러개 안만들고 어떻게 제어하지?
- 배열 + 상태를 별도로 관리할 수 있습니다.
!-->
자세한 설명 엄청 감사합니다.
근데 제 질문의 의도가 그게 아닌거 같아요.
제 질문의 의도는 예를들어
- 회원가입 페이지에서 아이디중복체크클릭시 해당 모달을 띄워야 할때
- 헤더 부분에서 무언가 클릭시 해당 모달을 띄워야 할때
- 또 어떤 다른 페이지에서 해당 모달을 띄워야 할때
이런 가정하에 회원가입페이지에 버튼이 있어야 하고 헤더 부분에 버튼이 있어야 하고 각각 다른 위치에 버튼이 있어야 하는 상태에서 app.jsx 에는 회원가입페이지에서 클릭한 모달과 헤더 부분에서 클릭한 모달 2가지의 내용이 다른 모달이 있어야 하잖아요?
app.jsx 에는 각기 다른 내용들의 모달들이 있고 각각 다른 페이지에서는 버튼만 있는 상태에서 클릭시 해당하는 모달을 열고 닫는..
제 의도는 이런 뜻이었습니다.
각각 다른 내용의 모달들이 app.jsx 에 모여있지만 각각의 버튼들은 다 다른 위치에 있는거죠
그게 리액트에서는 어렵네요... 각각 다른 페이지에서 버튼을 클릭했을 때 app.jsx 에 있는 해당하는 모달을 띄워주는 방법이요..
여기서 질문
- app.jsx 에 예제로 해주신것처럼 모달버튼하고 모달내용이 무조건 같은 페이지내에 있어야 하나요?
제껀 이렇게 되어있어요
클릭할 때 함수 인자로 뭘 중복하는지 체크 한다음에 모달창 띄워서 그안에 컨텐츠만 바꾸면 되는거니깐요
참고로 openNotification 은 알림창 같은거에요 제 기준으로 중복을 모달로 띄우기는 참 뭐해서^^;
이런 느낌이라 보시면 될꺼에요