[TIL] 230728

이세령·2023년 7월 28일
0

TIL

목록 보기
69/118

React JS -> Ts 리팩토링

App.tsx

id를 길이대신에 uuid로 변경해주고 Work를 type파일을 새로 만들어서 지정해주었다.

const clickAddButtonHandler = (event: React.FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    const newWorking: Work = {
      id: v4(),
      work: title,
      content: content,
      isDone: false,
    };
    const updateWorking = [...working, newWorking];
    setworking(updateWorking);
    localStorage.setItem("todokey", JSON.stringify(updateWorking));
    setTitle("");
    setContent("");
  };

그리고 Cards에 넘겨주는 함수들의 이름도 fnc1, fnc2 대신에 이름을 더 명확하게 변경해주고 수정을 위해 working의 State를 변수로 넘겨준다.

return (
    <div className="mytodo">
      <div className="title">
        <div>My Todo List</div>
        <div>React</div>
      </div>
      <div className="input-form">
        <form className="addform" onSubmit={clickAddButtonHandler}>
          <Input labelName={"제목"} value={title} Add={titleAddHandler}></Input>
          <Input
            labelName={"내용"}
            value={content}
            Add={contentAddHandler}
          ></Input>
          <button className="add-btn">추가하기</button>
        </form>
      </div>
      <div className="list">
        <h1>Working..</h1>
        <div>
          <div className="working">
            {working
              .filter((work) => {
                return work.isDone === false;
              })
              .map((item) => {
                return (
                  <Cards
                    key={item.id}
                    item={item}
                    deletefnc={clickDeleteButtonHandler}
                    statefnc={clickCompleteButtonHandler}
                    working={working}
                    setwork={setworking}
                  >
                    완료
                  </Cards>
                );
              })}
          </div>
        </div>
        <h1>Done..!</h1>
        <div>
          <div className="done">
            {working
              .filter((work) => {
                return work.isDone === true;
              })
              .map((item) => {
                return (
                  <Cards
                    key={item.id}
                    item={item}
                    deletefnc={clickDeleteButtonHandler}
                    statefnc={clickCancelButtonHandler}
                    working={working}
                    setwork={setworking}
                  >
                    취소
                  </Cards>
                );
              })}
          </div>
        </div>
      </div>
    </div>
  );

Cards.tsx

props의 타입은 다음과 같이 지정해줬다.

export interface CardsType {
  key: string;
  item: Work;
  deletefnc(id: string): void;
  statefnc(id: string): void;
  working: Work[];
  setwork: any;
  children: string;
}

수정 기능을 구현하기 위해 useRef를 사용해서 수정 기능이 담긴 class를 찾아 value를 사용할 수 있게 변경하였다.

const updateButtonHandler = () => {
    setUpdateState(!updateState);
  };

  const completeUpdateButtonHandler = (id: string) => {
    // 수정 title, content

    const findUpdateBoxTitle = (
      updateBoxRef.current?.querySelector(".update-title") as HTMLInputElement
    ).value;

    const findUpdateBoxContent = (
      updateBoxRef.current?.querySelector(
        ".update-content"
      ) as HTMLTextAreaElement
    ).value;

    const newSetting = (id: string) => {
      const working: Work[] = props.working;

      const newWorking = working.map((data) => {
        if (data.id === id) {
          return {
            ...data,
            work: findUpdateBoxTitle,
            content: findUpdateBoxContent,
          };
        }
        return data;
      });

      localStorage.setItem("todokey", JSON.stringify([...newWorking]));
      props.setwork(newWorking);
    };

    newSetting(id);

    updateButtonHandler();
  };

UpdateContent

먼저 타입을 지정해주고

export interface UpdateTextType {
  item: Work;
}

선언문들을 타입에 맞게 수정해줬다.

const UpdateContent = (props: UpdateTextType) => {
  const [newTitle, setnewTitle] = useState<string>(props.item.work);
  const [newContent, setnewContent] = useState<string>(props.item.content);

  const newTitleHandler = (event: React.ChangeEvent<HTMLInputElement>) => {
    setnewTitle(event.target.value);
  };

  const newContentHandler = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
    setnewContent(event.target.value);
  };

  return (
    <>
      <input
        className="update-title"
        type="text"
        value={newTitle}
        onChange={(event) => newTitleHandler(event)}
      ></input>
      <textarea
        className="update-content"
        value={newContent}
        onChange={(event) => newContentHandler(event)}
      ></textarea>
    </>
  );
};

Button 컴포넌트 타입 지정하기

props의 타입을 지정해야 하는데 event가 어떤 것인지 감이 안잡혔다.
하지만 해당 event 매개변수에 마우스를 올려보면 어떤 것인지 알려줬다.

const Button = (props: ButtonType) => {
  return (
    <button
      className={props.role}
      onClick={(event) => props.fnc(props.para.id, event)}
    >
      {props.children}
    </button>
  );
};

TodoType.ts

export interface ButtonType {
  role: string;
  para: Work;
  fnc(id: string, event: React.MouseEvent): void;
  children: string;
}

새로 알게 된 것

타입단언(as Type) 과 타입선언(:Type)

interface Person { 
    name: string;
}

const alice: Person = { name: 'Alice' }; // 타입은 Person  
const bob = { name: 'Bob' } as Person  ; // 타입은 Person

타입단언 사용을 지양해야 한다.

  • 타입단언
    타입체크 오류를 무시한다.

제네릭 Generics

  • 정의
    재사용성이 높은 컴포넌트를 만들 때 자주 활용되는 특징
    타입을 함수의 파라미터처럼 사용하는 것

  • 선언

function getText<T>(text: T): T {
  return text;
}
  • 사용할 때
getText<string>('hi');
getText<number>(10);
getText<boolean>(true);

해봤던 내용들이긴 하지만, React에서는 처음 적용해봐서 시간이 오래 걸리는 것 같다. 토요일에는 문서를 더 분석해보면서 공부해봐야겠다

profile
https://github.com/Hediar?tab=repositories

0개의 댓글