모달창
입력폼을 팝업으로 띄우려고 하기 위해서는 팝업표시 여부를 상태관리 해줘야한다.
Modal이라는 컴포넌트를 만들고 NewPost를 Modal이라는 컴포넌트 내부로 옮겨준다.
import { useState } from "react";
import Modal from "./Modal";
import NewPost from "./NewPost";
import Post from "./Post";
import classes from './PostsList.module.css'
function PostsList() {
const [enteredBody, setEnteredBody] = useState('');
const [enteredAuthor, setEnteredAuthor] = useState('');
function bodyChangeHandler(event) {
setEnteredBody(event.target.value);
}
function authorChangeHandler(event) {
setEnteredAuthor(event.target.value);
}
// 모달창 상태관리
const [modalIsVisible, setModalIsVisible] = useState(true);
function hideModalHandler() {
setModalIsVisible(false);
}
return (
<>
<Modal onClose={hideModalHandler}>
<NewPost onBodyChange={bodyChangeHandler} onAuthorChange={authorChangeHandler}/>
</Modal>
<ul className={classes.posts}>
<Post author = {enteredAuthor} body= {enteredBody}/>
<Post author = "ruby" body = "hello react"/>
</ul>
</>
);
}
export default PostsList;
import classes from "./Modal.module.css"
function Modal({children, onClose}) {
return (
<>
<div className={classes.backdrop} onClick={onClose}/>
<dialog open className={classes.modal}>{children}
</dialog>
</>
);
}
export default Modal;
// dialog의 open속성을 통해 팝업창을 호출한다. 기본값은 true
객체 구조 분해를 통해 props.children이 아닌 children키에 바로 접근할 수 있다.
여기서 children은 해당 컴포넌트 태그 내부의 컴포넌트 내용을 전달해주는 예약어이다.
여기서는 NewPost가 된다.
그리고 Modal의 표시여부를 상태관리하기 위해 useState등록을 하고 props로 onClose키값에 함수를 넣고 Modal에 전달해준다.
배경을 클릭했을 때 숨기기 위해 onClick으로 onClose를 넣어준다.
modalIsVisible의 값을 통해 숨겨줘야 하므로 조건을 달아준다.
let modalContent;
if(modalIsVisible) {
modalContent = (
<Modal onClose={hideModalHandler}>
<NewPost onBodyChange={bodyChangeHandler} onAuthorChange={authorChangeHandler}/>
</Modal>
);
}
return (
<>
{modalContent}
</>
);
이런식으로 컴포넌트 자체를 값에 할당하여 주거나
return (
<>
{modalIsVisible &&
(<Modal onClose={hideModalHandler}>
<NewPost onBodyChange={bodyChangeHandler} onAuthorChange={authorChangeHandler}/>
</Modal>)}
</>
);
&& 를 통해 true인 경우만 나오게끔 해주거나
return (
<>
{modalIsVisible ?
<Modal onClose={hideModalHandler}>
<NewPost onBodyChange={bodyChangeHandler} onAuthorChange={authorChangeHandler}/>
</Modal>
: null}
</>
);
3항 연산자로 처리할 수 있다.
공통 헤더 컴포넌트를 달아주어 팝업을 닫고 열수 있게 만들어 본다.
import { MdPostAdd, MdMessage } from 'react-icons/md';
import classes from './MainHeader.module.css';
function MainHeader({ onCreatePost }) {
return (
<header className={classes.header}>
<h1 className={classes.logo}>
<MdMessage />
React Poster
</h1>
<p>
<button className={classes.button} onClick={onCreatePost}>
<MdPostAdd size={18} />
New Post
</button>
</p>
</header>
);
}
export default MainHeader;
npm install react-icons로 아이콘을 사용하기 위한 라이브러리를 설치 해준다.
import { useState } from "react";
import MainHeader from "./components/MainHeader";
import Post from "./components/Post";
import PostsList from "./components/PostsList";
function App() {
// 모달창 상태관리
const [modalIsVisible, setModalIsVisible] = useState(false);
function hideModalHandler() {
setModalIsVisible(false);
}
function showModalHandler() {
setModalIsVisible(true);
}
return (
<>
<MainHeader onCreatePost={showModalHandler}/>
<main>
<PostsList isPosting={modalIsVisible} onStopPosting={hideModalHandler}/>
</main>;
</>
);
}
export default App;
App.jsx에 헤더를 넣고 헤더를 통해 팝업창을 상태관리 할 것이므로 PostsList.jsx에 있던 모달창 상태관리를 가져와 넣어준다.
동일하게 MainHeader에 onCreatePost 라는 props로 함수를 넘겨주고 MainHeader에서 받아서 처리한다.
그리고 PostsList에 isPosting, onStopPosting props를 전달하여 PostsList내부의 Modal을 관리해준다.
즉 App에서 팝업창 상태관리를 MainHeader와 PostsList와 연결시켜주는 것이다. 그리고 PostsList는 App에서 받은 값으로 Modal표시여부 조건을 처리해준다.