노트 생성 페이지 추가하기

이제 사용자를 등록하고 로그인할 수 있게 되었습니다. 이제 노트 작성 앱의 가장 중요한 부분인 노트 생성을 시작해 보겠습니다.

먼저 노트를 위한 폼을 만들겠습니다. 이 폼은 내용과 첨부 파일을 입력받습니다.

컨테이너 추가하기

Change indicator 새로운 파일 src/containers/NewNote.tsx를 생성하고 다음 내용을 추가합니다.

import React, {useRef, useState} from "react";
import Form from "react-bootstrap/Form";
import Stack from "react-bootstrap/Stack";
import {useNavigate} from "react-router-dom";
import LoaderButton from "../components/LoaderButton";
import config from "../config";
import "./NewNote.css";

export default function NewNote() {
  const file = useRef<null | File>(null);
  const nav = useNavigate();
  const [content, setContent] = useState("");
  const [isLoading, setIsLoading] = useState(false);

  function validateForm() {
    return content.length > 0;
  }

  function handleFileChange(event: React.ChangeEvent<HTMLInputElement>) {
    if ( event.currentTarget.files === null ) return
    file.current = event.currentTarget.files[0];
  }

  async function handleSubmit(event: React.FormEvent<HTMLFormElement>) {
    event.preventDefault();

    if (file.current && file.current.size > config.MAX_ATTACHMENT_SIZE) {
      alert(
        `파일 크기가 ${
          config.MAX_ATTACHMENT_SIZE / 1000000
        } MB보다 작아야 합니다.`
      );
      return;
    }

    setIsLoading(true);
  }

  return (
    <div className="NewNote">
      <Form onSubmit={handleSubmit}>
        <Form.Group controlId="content">
          <Form.Control
            value={content}
            as="textarea"
            onChange={(e) => setContent(e.target.value)}
          />
        </Form.Group>
        <Form.Group className="mt-2" controlId="file">
          <Form.Label>첨부 파일</Form.Label>
          <Form.Control onChange={handleFileChange} type="file" />
        </Form.Group>
        <Stack>
          <LoaderButton
            size="lg"
            type="submit"
            variant="primary"
            isLoading={isLoading}
            disabled={!validateForm()}
          >
            생성
          </LoaderButton>
        </Stack>
      </Form>
    </div>
  );
}

여기서는 파일 입력을 제외하고는 모두 표준적인 내용입니다. 지금까지의 폼 엘리먼트는 컨트롤드 컴포넌트로, 값이 컴포넌트의 상태에 의해 직접 제어되었습니다. 그러나 파일 입력의 경우 브라우저가 이 상태를 처리하도록 하고 싶습니다. 따라서 useState 대신 useRef 훅을 사용합니다. 두 가지의 주요 차이점은 useRef가 컴포넌트를 리렌더링하지 않는다는 점입니다. 단순히 React에게 나중에 사용할 수 있도록 값을 저장하도록 지시합니다. current 속성을 사용하여 ref의 현재 값을 설정하거나 가져올 수 있습니다. 사용자가 파일을 선택할 때와 동일한 방식으로 사용합니다.

file.current = event.target.files[0];

현재 handleSubmit은 첨부 파일의 크기를 제한하는 것 외에는 별다른 기능을 하지 않습니다. 이 설정을 config에 정의할 것입니다.

Change indicator src/config.ts 파일의 const config = { 줄 아래에 다음 내용을 추가합니다.

// 프론트엔드 설정
MAX_ATTACHMENT_SIZE: 5000000,

Change indicator 또한 src/containers/NewNote.css에 폼 스타일을 추가합니다.

.NewNote form textarea {
  height: 300px;
  font-size: 1.5rem;
}

라우트 추가하기

Change indicator 마지막으로, src/Routes.tsx 파일에서 회원가입 라우트 아래에 우리의 컨테이너를 라우트로 추가합니다.

<Route path="/notes/new" element={<NewNote />} />

Change indicator 그리고 헤더에 컴포넌트를 포함시킵니다.

import NewNote from "./containers/NewNote.tsx";

이제 브라우저로 전환하여 /notes/new로 이동하면 새로 생성된 폼을 볼 수 있습니다. 내용을 추가하고 파일을 업로드한 후 제출 버튼을 눌러 동작을 확인해 보세요.

새 노트 페이지 추가 스크린샷

다음으로, 이 폼을 API에 연결하는 방법을 알아보겠습니다.