목표 : 리팩토링은 여러가지가 있지만 이번 포스팅에서는 컨텐츠 2개를 겹쳐서 렌더링하는 작업을 진행할 것이다.
해법 : 래핑한다. ex) NewPost를 모달(백드롭)로 감싸고 싶다면 form요소를 Modal 컴포넌트로 감싼다.
이전 시간에 레이아웃 라우트를 추가해주고, 레이아웃 라우트에 필요한 여러 속성들을 설정해주었다. 가장 아랫단에 위치할 컴포넌트 객체로 기존에 추가해줬던 객체들을 안에 래핑되게 해주었고, 래핑하고 있는 가장 아랫단의 루트 컴포넌트인 RootLayout 컴포넌트에서 Oulet
컴포넌트를 추가해 래핑된 컴포넌드들이 어디에 표시될지 추가해주었다.
그런데 기존 App.jsx
에서 MainHeader
를 렌더링 하고 있었기에 추가 수정이 필요했다.
그런데 단순히 MainHeader만 삭제한다고 되는것이 아니라, 라우터, 레이아웃 라우터를 사용했기 때문에 여러가지의 리팩토링 작업이 필요하다.
Post
컴포넌트를 비롯해서 NewPost
PostList
App
컴포넌트 등등 많은 것들을 수정해야한다.
라우트에서 로딩되는 것들은 라우트 폴더로 이외의 다른 컴포넌트들은 컴포넌트 폴더로 분리 작업을 먼저 진행한다.
메인헤더쪽 부터 리팩토링 진행하는데 이름과 메인헤더부분 코드에서 삭제한다.
✍ App.jsx (수정 전)
import { useState } from "react";
import PostList from "../components/PostList";
import MainHeader from "../components/MainHeader";
function App() {
const [modalIsVisible, setModalIsVisible] = useState(false);
function showModalHandler() {
setModalIsVisible(true);
}
function hideModalHandler() {
setModalIsVisible(false);
}
return (
<>
<MainHeader onCreatePost={showModalHandler} />
<main>
<PostList isPosting={modalIsVisible} onStopPosting={hideModalHandler} />
</main>
</>
);
}
export default App;
✍ Posts.jsx (수정 후)
import { useState } from "react";
import PostList from "../components/PostList";
function Posts() {
return (
<>
<main>
<PostList />
</main>
</>
);
}
export default Posts;
진행상황
- 헤더 중첩 되는 에러 수정 완료
- NewPost 컴포넌트 동작 여전히 안됨
- 당연하게 레이아웃 되는 Modal 등등 추가 동작들도 아직 연결 안됨
PostList
부분도 삭제 할 예정.
목표 : NewPost 컴포넌트 동작 & 렌더링
이것도 위와 동일하게 라우터에서 렌더링 될 것이므로
폴더이동을 마치고 NewPost 컴포넌트 path인 "/create-post"을 웹 주소창에 추가해서 엔터 해보면 포스트 목록 위에 표시되는 오버레이 스타일이 아니라 달랑 NewPost 컴포넌트 하나만 렌더링 된다.
✍ main.jsx
const router = createBrowserRouter([
{
path: "/",
element: <RootLayout />,
chlidren: [
//생략
{
path: "/create-post",
element: <NewPost />,
},
],
},
]);
이 NewPost 컴포넌트는 모달로 로드해야 한다. 그래서
기존에는 PostList
에서 렌더링 하고 있었지만 NewPost
컴포넌트에서 Form
을 Modal
컴포넌트로 래핑한다.
✍ NewPost.jsx (코드 추가 후)
import Modal from "../components/Modal";
function NewPost(props) {
// 중략 위의 import 한 부분, 상태관리 코드 전부 생략.
return (
<Modal>
<form className={classes.form} onSubmit={submitHandler}>
<p>
<label htmlFor="body">Text</label>
<textarea id="body" required rows={3} onChange={bodyChangeHandler} />
</p>
<p>
<label htmlFor="name">Your name</label>
<input
type="text"
id="name"
required
onChange={authorChangeHandler}
/>
</p>
<p className={classes.actions}>
<button type="button" onClick={props.onCancel}>
Cancel
</button>
<button>Sumbit</button>
</p>
</form>
</Modal>
);
}
export default NewPost;
따라서 삭제할 부분들
1. Modal에 NewPost 컴포넌트를 렌더링하는 부분삭제.
2.dddd
✍ PostList.jsx (삭제 후 코드)
import { useEffect, useState } from "react";
import Post from "./Post";
import classes from "./PostList.module.css";
function PostList({ isPosting, onStopPosting }) {
const [posts, setPosts] = useState([]);
const [isFetchting, setIsFetching] = useState(false);
useEffect(() => {
async function fetchPosts() {
setIsFetching(true);
const response = await fetch("http://localhost:8080/posts");
const resData = await response.json();
if (!response.ok) {
<div style={{ textAlign: "center", color: "white" }}>
<p>응답이 비정상적입니다...</p>
</div>;
}
setPosts(resData.posts);
setIsFetching(false);
}
fetchPosts();
}, []);
function addPostHandler(postData) {
fetch("http://localhost:8080/posts", {
method: "POST",
body: JSON.stringify(postData),
headers: {
"Content-Type": "application/json",
},
});
setPosts((existingPosts) => [postData, ...existingPosts]);
}
return (
<>
{!isFetchting && posts.length > 0 && (
<ul className={classes.posts}>
{posts.map((post) => (
<Post key={post.body} author={post.author} body={post.body} />
))}
</ul>
)}
{!isFetchting && posts.length === 0 && (
<div style={{ textAlign: "center", color: "white" }}>
<h2>포스트가 없습니다.</h2>
<p>여기에 내용을 추가해보세요 !</p>
</div>
)}
{isFetchting && (
<div style={{ textAlign: "center", color: "white" }}>
<p>게시물 로딩중...</p>
</div>
)}
</>
);
}
export default PostList;
와 여기까지 했는데 라우팅 설정이 안됐다면서 계속 오류가 났다. 2시간 찾아헤맸는데 ChatGPT 덕분에 찾아냈다....... 진짜 최고다 GPT
결국 main.jsx 스크립트에서 스크립트 라우트 설정해주는 부분에 오타 하나 떄문에 생긴 문제였다.
children 을
chlidren 으로 잘못입력했던것, ;;;
아니 근데 vscode야 왜 오타 안알려주니......
const router = createBrowserRouter([
{
path: "/",
element: <RootLayout />,
children: [
{ path: "/", element: <App /> },
{ path: "/create-post", element: <NewPost /> },
],
},
]);