TC - 17번일지 (리팩토링 3)

Debug-Life ·2023년 3월 21일
0

7. 기존의 cancel, submit 버튼 리팩토링

이전시간 복습 & 정리

이전 시간까지 했던 것들은 원하는 페이지들을 각각 라우트 별로 분리해서 추가해주었고, 중첩이 되어 렌더링 되어야 할 컴포넌트들은 레이아웃 라우트로 설정해주었다.

결과적으로 여태까지 MainHeader 가 위치한 RootLayout 컴포넌트가 가장 아랫단에 위치한 레이아웃 컴포넌트로 그 위에 Posts 또 그 위에(그러니까 자식으로) NewPost컴포넌트를 렌더링 하고 있다.

추가로 spa의 특성을 유지하기 위해 백엔드로 보내지 말아야할 것들을 위해 Link 컴포넌트로 사용자 경험을 좋게 유지시켰다.

목표 : 기존의 백드롭 , cancel, submit 버튼 동작하도록 리팩토링


7-1. 백드롭 리팩토링

우선 닫는 동작부터 처리하겠다. Modal창에서 Props을 전달 받아서 닫아주는 클릭 이벤트 부분은 삭제.
왜냐하면 Modal 컴포넌트 안에서 직접 Click 이벤트를 처리할 것이기 떄문에. 이 Modal에는 항상 래핑할 페이지가 있다고 가정하고 라우트 안에서 Modal을 래퍼처럼 사용할 예정임.

다시 말해서 모달의 백드롭을 클릭하면 다른 라우트로 이동할 것임.

✍ Modal.jsx (절대경로 '/' 코드)

import { useNavigate } from "react-router-dom";
import classes from "./Modal.module.css";

function Modal(props) {
  const navigate = useNavigate();

  function closeHandler() {
    navigate("/");
  }

  return (
    <>
      <div className={classes.backdrop} onClick={closeHandler} />
      <dialog open={true} className={classes.modal}>
        {props.children}
      </dialog>
    </>
  );
}

export default Modal;

✍ Modal.jsx (상대경로 ..코드)

import { useNavigate } from "react-router-dom";
import classes from "./Modal.module.css";

function Modal(props) {
  const navigate = useNavigate();

  function closeHandler() {
    navigate("..");
  }

  return (
    <>
      <div className={classes.backdrop} onClick={closeHandler} />
      <dialog open={true} className={classes.modal}>
        {props.children}
      </dialog>
    </>
  );
}

export default Modal;

수정 코드 내용

  • 링크가 아니라 div 요소가 클릭됐을 때 페이지를 이동하게 설정.
  • 이전 포스팅에서 본 것 처럼, div 대신 Link 사용해도 되지만 여기서는 div를 사용해 프로그램적으로 경로를 탐색하는 방법을 사용함.
  • closeHandler 가 실행됐을 때 이동할 경로를 인자로 넘겨준다. 그래서 저장하고 실행하고서 백드롭을 클릭해 보면 다시 시작 페이지로 이동하는데 성공
  • 상대경로 '..' 을 쓰면 터미널 창에서 cd 명령어에 ..를 쓴 것과 동일하다. 라우팅에서도 마찬가지다. 그냥 useNavigate 는 터미널에서 경로 이동하게 알려주는 훅이라 생각하자.
  • 그런데 상대경로를 쓰는것이 좀 더 동적이기 떄문에 상대경로로 설정하기.



✍ main.jsx (경로 확인하자)

import React from "react";
import ReactDOM from "react-dom/client";
import { RouterProvider, createBrowserRouter } from "react-router-dom";

import Posts from "./routes/Posts";
import NewPost from "./routes/NewPost";
import RootLayout from "./routes/RootLayout";
import "./index.css";

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

ReactDOM.createRoot(document.getElementById("root")).render(
  <React.StrictMode>
    <RouterProvider router={router} />
  </React.StrictMode>
);

그러니까 바로 위 main.jsx 코드에서 보면 /create-post 에서 한단계 부모가 Posts 컴포넌트고 그 경로가 "/", 인걸 확인 할 수 있다.



7-2. cancel 버튼 리팩토링

✍ NewPost.jsx (수정 후 코드)

import { useState } from "react";
import { Link } from "react-router-dom";

import Modal from "../components/Modal";
import classes from "./NewPost.module.css";

function NewPost(props) {
  const [enteredBody, setEnteredBody] = useState("");
  const [enteredAuthor, setEnteredAuthor] = useState("");

  function bodyChangeHandler(event) {
    setEnteredBody(event.target.value);
  }
  function authorChangeHandler(event) {
    setEnteredAuthor(event.target.value);
  }
  function submitHandler(event) {
    event.preventDefault();
    const postData = {
      body: enteredBody,
      author: enteredAuthor,
    };
    props.onAddPost(postData);
    props.onCancel();
  }

  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}>
          <Link to=".." type="button">
            Cancel
          </Link>
          <button>Sumbit</button>
        </p>
      </form>
    </Modal>
  );
}

export default NewPost;

여기까지 하고 저장하면 cancel 버튼도 라우팅으로 제대로 동작한다.

수정내용

  • NewPost 컴포넌트에 위치해 있을 것이고, 여기선 Link를 사용해 처리해보겠다.
  • Link 설정 (to 로 경로설정)
  • onClick 이벤트 핸들러 필요없어서 삭제
  • 이렇게 해서 라우트 사이를 이동할 수 있게 만들었다. 이전과 동작 차이는 크게 없지만 라우팅을 이용하는것이 매우 큰 차이다. 라우팅을 사용하는 목적은 사용자들에게 해당 페이지를 공유하려는 것이고, 이것이 라우팅을 사용하는 목적이다. 그러니까 동작은 같아도 아주 큰 차이인 것이다.





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

0개의 댓글