TC - 15번일지 (리팩토링 1)

Debug-Life ·2023년 3월 19일
0

21. 리팩토링

목표 : 리팩토링은 여러가지가 있지만 이번 포스팅에서는 컨텐츠 2개를 겹쳐서 렌더링하는 작업을 진행할 것이다.

해법 : 래핑한다. ex) NewPost를 모달(백드롭)로 감싸고 싶다면 form요소를 Modal 컴포넌트로 감싼다.

이전 시간에 레이아웃 라우트를 추가해주고, 레이아웃 라우트에 필요한 여러 속성들을 설정해주었다. 가장 아랫단에 위치할 컴포넌트 객체로 기존에 추가해줬던 객체들을 안에 래핑되게 해주었고, 래핑하고 있는 가장 아랫단의 루트 컴포넌트인 RootLayout 컴포넌트에서 Oulet 컴포넌트를 추가해 래핑된 컴포넌드들이 어디에 표시될지 추가해주었다.

그런데 기존 App.jsx에서 MainHeader 를 렌더링 하고 있었기에 추가 수정이 필요했다.
그런데 단순히 MainHeader만 삭제한다고 되는것이 아니라, 라우터, 레이아웃 라우터를 사용했기 때문에 여러가지의 리팩토링 작업이 필요하다.
Post 컴포넌트를 비롯해서 NewPost PostList App 컴포넌트 등등 많은 것들을 수정해야한다.


21-1. route, component 폴더 분리

라우트에서 로딩되는 것들은 라우트 폴더로 이외의 다른 컴포넌트들은 컴포넌트 폴더로 분리 작업을 먼저 진행한다.

App.jsx 리팩토링

메인헤더쪽 부터 리팩토링 진행하는데 이름과 메인헤더부분 코드에서 삭제한다.

✍ 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.jsx 리팩토링

목표 : NewPost 컴포넌트 동작 & 렌더링

1. 폴더이동.

이것도 위와 동일하게 라우터에서 렌더링 될 것이므로

2. 문제 발생

폴더이동을 마치고 NewPost 컴포넌트 path인 "/create-post"을 웹 주소창에 추가해서 엔터 해보면 포스트 목록 위에 표시되는 오버레이 스타일이 아니라 달랑 NewPost 컴포넌트 하나만 렌더링 된다.

✍ main.jsx

const router = createBrowserRouter([
  {
    path: "/",
    element: <RootLayout />,
    chlidren: [
      //생략
      {
        path: "/create-post",
        element: <NewPost />,
      },
    ],
  },
]);

3. 해결방법

이 NewPost 컴포넌트는 모달로 로드해야 한다. 그래서
기존에는 PostList 에서 렌더링 하고 있었지만 NewPost 컴포넌트에서 FormModal 컴포넌트로 래핑한다.

✍ 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;

4. PostList 컴포넌트 정리

  • 더이상 여기서 포스트 추가작업 하지 않음.
  • 대신 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 /> },
    ],
  },
]);



profile
인생도 디버깅이 될까요? 그럼요 제가 하고 있는걸요

0개의 댓글