[Typescript pair study] my AgoraStates Typescript 리팩토링 코드 공유 세션 ①

이민선(Jasmine)·2023년 5월 13일
2
post-thumbnail

3번째 세션!

이번주부터는 코드스테이츠 DOM 과제였던 my Agora States를 React/typescript로 리팩토링해오고, 각자 특정 상황에서 어떤 type을 주었는지 발표하며 공유하는 방식으로 스터디를 진행한다.

💡 나의 과제

이번 주 진행 상황 요약

store.tsx

  • Redux toolkit 이용하여 서버에서 받은 discussions를 보관하는 store 구축

Discussions.tsx

  • 질문 생성 기능 추가

Paginations.tsx, PageBtns.tsx

  • store에서 useSelector를 통해 가져온 질문 목록에 페이지네이션 기능 추가

Type 발표

1. 서버에서 가져온 배열 원소에 Alias type인 Discussion 지정, 속성에 tuple type 지정

export type Discussion = {
  answer: {
    author: string;
    avatarURL: string;
    bodyHTML: string;
    createdAt: string;
    id: number;
    url: string;
  } | null;
  author: string;
  avatarURL: string;
  bodyHTML: string | null;
  createdAt: string;
  id: number;
  url: string | null;
  title: string;
  updatedAt: string | null;
};

서버에서 가져온 데이터와 새로 추가하는 데이터의 타입을 고려하여 각 discussion에 alias type을 지정해주었다. answer 속성의 경우 답변이 달리지 않았을 경우 값이 null이므로, 이를 반영하여 tuple type으로 null도 지정해주었다.

2. useState에 초기값의 type을 제네릭인 <Discussion[]>로 지정

const [currentItems, setCurrentItems] = useState<Discussion[]>([]);

useState 훅 사용 시 변수의 타입을 Discussion[]으로 지정하는 것이다. setCurrentItems 함수의 파라미터도 Discussion[] type으로 자동 추론되기 때문에, 다른 type의 값을 setCurrentItems의 인자로 전달할 경우 type error가 난다.

아직 나도 수민님도 제네릭은 기초 타입 세션 때 못 다뤘어서, 이번에 발표할 때도 깊은 내용까지 설명하는 데에 한계가 있었다. 다다음 세션 때 수민님과 함께 스터디에서 제네릭도 다룰 예정이다.

3. event 객체: React 기본 제공 제네릭 타입 지정

// input에 onChange 함수 연결
  const onChangeUserName = (event: React.ChangeEvent<HTMLInputElement>) => {
    setUserName(event.currentTarget.value);
  };
// textarea에 onChange 함수 연결
  const onChangeDiscussionTitle = (
    event: React.ChangeEvent<HTMLTextAreaElement>
  ) => {
    setDiscussionTitle(event.currentTarget.value);
  };
// form에 onSubmit 함수 연결
  const onSubmit = (event: React.FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    if (userName.length === 0 || discussionTitle.length === 0) return;
    dispatch(
      createDiscussion({
        answer: null,
        author: userName,
        avatarURL: null,
        bodyHTML: null,
        createdAt: JSON.stringify(new Date()),
        id: Date.now(),
        url: null,
        title: discussionTitle,
        updatedAt: null,
      })
    );
    setUserName("");
    setDiscussionTitle("");
  };
// 페이지 전환 버튼에 onClick 함수 연결
    const onClick = (event: React.MouseEvent<HTMLButtonElement>) => {
    onPageChange(Number(event.currentTarget.textContent));
  };

onChange, onSubmit, onClick 등 이벤트 객체를 매개변수로 지정할 때에는 React에서 제공하는 이벤트 객체 제네릭 타입을 사용해야 한다. 이벤트 type, 이벤트가 발생한 tag가 포함되어 있다. 이벤트가 발생한 tag 쯤은 바로 알 수 있지만, 어떤 이벤트인지 (MouseEvent, FormEvent 등등) 바로바로 떠올리는 게 헷갈린다. 당분간은 나도 수민님도 일일히 다 외우기보다는 이벤트를 키워드로 검색해서 필요할 때 그 때 그 때 찾아보는 게 좋을 것 같다.

4. PageBtns 컴포넌트로 받아오는 props에 interface 지정

interface IPageBtns {
  itemsPerPage: number;
  totalPages: number;
  onPageChange: (buttonNumber: number) => void;
}

function PageBtns({ itemsPerPage, totalPages, onPageChange }: IPageBtns) {
.
.

itemsPerPage, totalPages는 number여서 어렵지 않았는데, useState의 modifier 함수인 onPageChange는 type을 어떻게 지정해야할지 잘 몰라서 찾아보았다. 매개변수의 type, return 하는 값의 type을 지정하는 방식으로 표현하면 된다.

5. 페이지네이션: 한 페이지에 보여줄 수 있는 게시물의 수를 union type으로 미리 지정

function Pagination() {
  type ItemsPerPage = 7 | 10;

  const itemsPerPage: ItemsPerPage = 7;
  .
  .

7개 또는 10개로 지정했다. 7개씩 보기, 10개씩 보기 toggle 버튼을 만들 예정이기 때문이다. 다른 숫자를 지정하면 가차없이 type 오류 나도록 만들었다. ㅎㅎㅎㅎ

이번 세션 회고

이번에 내가 발표한 type들은 react로 토이 프로젝트를 할 때도 피해갈 수 없는 type들이었다. redux store에 객체 원소 추가, useState 훅 사용, event 객체, props 넘겨 받기 이거 안하는 프로젝트가 과연 있을까?! 있을 수가 있나? 잘 모르겠지만 적어도 우리에겐 앞으로 없을 것 같다. 가장 빈번하게 사용되는 type 위주로 공유할 수 있는 시간이어서 값졌다.

다만 아쉬운 점도 있었다. 일단 이번 스터디 과제 하면서 제네릭 타입을 많이 사용하게 되었는데, 기초 세션에서 미리 다룰 생각을 미리 못했던 점이 아쉬웠다. 제네릭 기초를 잘 다진 다음 my Agora State을 했으면, 발표하면서 얘기할 거리도 더 풍부했을 것 같다. 지금은 나도 어렴풋이 알고 있는 상태에서 단순히 쓰임새만 얘기하게 되다보니 아쉬웠다.

그래서 다다음주까지 제네릭을 각자 공부해와서 제네릭 기초 세션도 한 번 가질 예정이다. 스터디 하다보니 내가 부족한 파트도 더 체계적으로 파악하게 된다.

수민님은 과제 시작 후 폭풍 에러 직면..!🥲 그래도 이번 시간에 같이 힘을 합쳐서 뚝딱뚝딱 에러들을 모두 잡을 수 있었다. 피해갈 수 없는 신고식 같은 느낌 ㅜ ㅜ ㅋㅋㅋㅋ (나는 맨날 신고식 하는 건가 ?! ㅋㅋㅋㅋㅋ) 어려움이 생기면 꼭 스터디 시간이 아니더라도 공유하고 함께 해결할 수 있는 분위기를 강화할 수 있는 방법이 있을지도 고민해봐야겠다는 생각이 들었다!!

📢 수민님 이번주 좋은 시작이었어요!! 솔로 프로젝트 하면서 강해져서 돌아와요 우리!! ㅋㅋㅋㅋㅋ 화이팅!!😊👍💪🏻

profile
기록에 진심인 개발자 🌿

0개의 댓글