Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[2주차] 권가은 미션 제출합니다. #5

Open
wants to merge 18 commits into
base: master
Choose a base branch
from

Conversation

Gaeun-Kwon
Copy link
Member

@Gaeun-Kwon Gaeun-Kwon commented Mar 24, 2023

🦔 배포 링크

2주차 미션 결과 화면


🦔 Overview

  • 저는 CSS Module에 더 익숙한 편이라, 이번 과제를 하면서 오랜만에 Styled-Components를 사용해봤습니다!
    CSS 방법론에 대해 블로그에 정리도 해보았어요.
  • 삭제 Modal도 별도의 컴포넌트로 두면 좋을 것 같습니다
  • 세오스 재밌따..

🦔 미션

미션 목표

  • VSCode, Prettier를 이용하여 개발환경을 관리합니다.
  • React의 기초를 이해합니다.
  • React를 통한 어플리케이션 상태 관리 방법을 이해합니다.
  • React Hooks에 대한 기초를 이해합니다.
  • Styled-Components를 통한 CSS-in-JS 및 CSS Preprocessor의 사용법을 익힙니다.

Key Questions

1. Virtual-DOM은 무엇이고, 이를 사용함으로서 얻는 이점은 무엇인가요?

Virtual-DOM:
React, Vue.js 와 같은 웹 프레임워크에서 사용되는, 실제 DOM의 경량 JavaScript 표현.

DOM 조작이 일어나면, 렌더트리 생성과 레이아웃 계산을 다시하며 리렌더링이 발생합니다.

따라서 모든 변경사항에 대해 매번 DOM을 변경하는 것은 비효율적입니다. 특히나 DOM 조작이 자주 일어나는 SPA에서는 더더욱..

따라서 우리는 Virtual DOM을 사용합니다.
가상DOM은 DOM 노드 트리를 복제한 자바스크립트 객체입니다. class, style 등의 속성은 있지만, DOM의 API 메서드는 갖고 있지 않습니다.


실제 DOM을 간략한 JavaScript object 바꾼 다음, 이것을 가지고 시뮬레이션을 해 보다가, 그 중 가장 경제적으로 DOM에 변화를 가하는 방법을 적용하는 방법을 사용합니다. 즉, 실제 DOM 에 적용되기 전에 Virtual-DOM에 먼저 적용시키고 그 최종적인 결과를 실제 DOM 으로 전달해줍니다.
이를 통해 브라우저 내에서 발생하는 연산의 양을 줄이면서 성능이 개선되는 효과를 누리게 됩니다. 😄

하지만 Virtual-DOM 을 사용하는 것이 무조건적인 해결책은 아닙니다.
DOM을 직접 제어하는 것과 비교 시 적은 비용이 들 뿐, 최적화를 제대로 해주지 않는다면 반복된 렌더링으로 인한 성능 저하를 겪을 수 밖에 없습니다.


2. 미션을 진행하면서 느낀, React를 사용함으로서 얻을수 있는 장점은 무엇이었나요?

이번 과제를 하며 바닐라JS에 비해 React를 사용하며 느낀 장점은 다음과 같습니다.

  • JSX 사용으로 인해, html과 js 파일을 왔다갔다 하지 않아도 된다.
  • state 를 사용하여, 자주 변경되는 변수를 사용하기 쉬워진다.

또한, 평소 React를 사용하며 느낀 다른 장점들도 있습니다:

  • Component의 재사용을 통한 깔끔한 코드 작성, 유지 보수 용이
  • Virtual DOM 사용을 통한 성능 개선

3. React에서 상태란 무엇이고 어떻게 관리할 수 있을까요?

  • React 상태(State)
    state는 컴포넌트 안에서 관리 되고 시간이 지나면서 바뀌는 동적인 데이터(객체)입니다. state가 바뀔때마다 컴포넌트가 리렌더 됩니다.

    컴포넌트들 사이에서는 props 형태로 state를 공유합니다.
    React는 단방향 데이터 흐름을 가지기 때문에, 부모 -> 자식 컴포넌트의 방향으로 props를 전달하는 Props Drilling 과정이 일어납니다.
    이때, 컴포넌트 계층이 많아지면 props 추적과 코드 이해가 어려워지고, 중간 단계에 있는 컴포넌트들이 불필요한 props를 들고 있어야 하는 문제가 발생합니다.
    때문에 React의 상태 관리가 필요해집니다.

  • React의 상태 관리

1. React Hooks
함수형 컴포넌트에서, state와 리액트의 생명주기 기능을 연결(hook into)할 수 있게 해주는 함수.
대표적으로 useState, useEffect가 있습니다.

  • 라이브러리를 통하지 않고 직접 state를 관리하는 방법
  • 규모가 있는 프로젝트에서 사용 시 지나친 props drilling 발생 가능

2. Redux
JavaScript(자바스트립트) 상태관리 라이브러리.

a. 구조
flux패턴을 사용, 데이터가 단방향으로 흐르는 구조를 갖는다.

  • Store: state가 저장, 관리되는 유일한 하나의 공간
  • Action: type과 전송할 데이터(payload)로 이루어진 JS 객체 형태 데이터. 앱에서 스토어에 운반할 데이터.
  • Dispatcher 함수: action을 전달
  • Reducer: state 조작. 현재(이전)의 state와 받은 action에 따라 그 state를 변화시킨 다음 새로운 state를 반환.

b. 특징

  • 유저가 많은, 검증된 라이브러리라는 장점
  • 비동기 데이터 처리를 위해 또 다른 라이브러리를 사용해야 함.
  • 러닝커브가 있다.

3. Recoil
React 전용 상태관리 라이브러리. Facebook의 Recoil 소개 영상 참고

a. 구조
atom → selector → view 의 data-flow

  • Atom: 컴포넌트가 구독할 수 있는 리액트 state. 우리가 전역적으로 사용하길 원하는 state를 atom이라는 걸로 띄워서(페북은 비눗방울이라고 표현) 어디서든지 사용할 수 있도록 함.
  • Selector: atoms나 다른 selectors를 입력으로 받는 순수 함수(pure function). atom을 활용해 개발자가 원하는 대로 값을 뽑아서 사용할 수 있는 API.

b. 특징

  • React 내부의 상태를 활용하고 context API를 통해 구현되어 있어, React스러운 라이브러리
  • 리액트 useState 훅과 비슷하게 동작하는, 직관적이면서 간단한 구조. 낮은 러닝커브, 간단한 코드.
  • 비동기 처리를 기반으로 작성되어 동시성 모드를 제공. 다른 라이브러리 필요x.

4. Styled-Components 사용 후기 (CSS와 비교)

Styled-Components 는 대표적인 CSS-in-JS 라이브러리입니다.
Facebook 개발자 Vjeux의 2014년 발표에서 소개된 개념인 CSS-in-JS는, 전통적인 CSS와 비교했을때 다음과 같은 장점이 있습니다.

  • Global namespace: class명이 빌드 타임에 유니크하게 변경되기 때문에 별도의 명명 규칙이 필요치 않음
  • Dependencies: CSS가 컴포넌트 단위로 추상화되기 때문에 CSS간 의존성 고려가 필요없음 (모듈성)
  • Dead Code Elimination: (주로) 컴포넌트와 CSS가 동일한 파일내에 존재하기 때문에 수정 및 삭제가 용이
  • Minification: 빌드 타임에 짧은 길이의 유니크한 클래스를 자동으로 생성하여 문서 사이즈를 낮춰줌 (코드 경량화)
  • Sharing Constants: CSS 코드가 JS에 작성되므로 상태 공유가 가능
  • Non-deterministic Resolution: CSS가 컴포넌트 스코프로 적용되므로 우선순위에 따른 문제가 없음
  • Isolation: CSS가 컴포넌트에 격리되어 있기 때문에 상속 문제가 없음

CSS-in-CSS 방법인 CSS Module을 주로 사용하던 저에게는,

  • CSS 파일을 왔다갔다 하지 않아도 되는 점
  • CSS 코드가 JS에 작성되므로 상수, 함수를 공유할 수 있다는 점

정도가 가장 크게 체감되었습니다.
앞으로 Styled-Components 사용에 좀 더 익숙해진다면 간편한 작업이 가능하다는 장점도 느낄 수 있을 것 같아요.

이와 관련해 추가로 알아보며 작성한 블로그 글


필수 요건

  • 1주차 미션의 결과물을 그대로 React로 구현합니다
  • Functional Components를 사용합니다
  • React Hooks만을 사용해 상태를 관리합니다
    (이번주는 Redux, MobX, Recoil, SWR등의 외부 상태관리 라이브러리를 사용하지 않아도 미션 수행에 지장이 없습니다.)

선택 요건

  • 기존 Todo-list에 여러분들이 추가하고 싶은 기능과 디자인을 자유롭게 추가해보세요.

Copy link
Member

@moong23 moong23 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

전체적으로 코드가 너무 깔끔하고 구조도 깔끔하게 작성된 것 같아요!
코드 리뷰를 하면서 아직도 부족한게 많고 배울게 많다는 것을 또 알게 되었습니다...
특히 propTypes를 사용해서 typechecking을 할 수 있다는 것을 알고 너무 뜻깊었던 것 같습니다...!

state관리하는 부분에 대해서는 더 공부해보고 알게 되는게 있다면 다시 수정하도록 하겠습니다!!!!
한주간 너무 고생 많으셨어요!! 스터디때 뵐게요 👋

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

약속의 파비콘ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ

이분꺼 업데이트된 (님들이) 만들어 쓰는 개발진스입니당

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ㅋㅋㅋㅋㅋㅋ 파비콘 보자마자 리뷰하러 왔는데 역씨... 😸

@@ -2,42 +2,19 @@
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<link rel="icon" href="%PUBLIC_URL%/favicon.png" />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

파비콘을 쓸 때는 png를 넣는것보다 확장자 변경 사이트에서 ico 확장자로 변경해서 넣는게 좋다고합니다!!
링크

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오 ico 확장자를 사용해서 여러개 사이즈를 정해두면 해상도 문제 없이 사용할 수 있겠네요!
자료 첨부까지 감사합니다 👍👍

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

우와웅 저도 이건 처음 알았어요!! 좋은 정보 감사합니다💪🏻

});
setTodoList(tempList);

localStorage.setItem(TODOKEY, JSON.stringify(tempList));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

옹... TODOKEY로 localStorage에 넣어주는 방법 되게 좋은 것 같아요..!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

string value는 최대한 변수로 만들어두고 사용하는 게 오류 사전 방지, 유지보수 측면에서 좋은 것 같아 이렇게 사용하고 있습니다! ㅎㅎ

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저도 string으로 사용했었는데 변수로 만들어 두는 것이 더 좋겠네요!! 이렇게 또 배워갑니다ㅠㅠ👏🏻👏🏻👏🏻

Comment on lines +49 to +56
ListContainer.propTypes = {
title: PropTypes.string,
todoList: PropTypes.array,
setTodoList: PropTypes.func,
isDone: PropTypes.bool,
setIsVisibleModal: PropTypes.func,
setSelectedTodo: PropTypes.func,
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

propTypes를 쓰는 건 처음 봤네요. typesciprt에서만 사용하는 줄 알았는데 js에서도 사용할 수 있다는걸 알아갑니다!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TS를 사용하다가 이번 과제를 하며 JS로 하려니 역체감을 느꼈어요..
그래서 기존에 JS로 React 사용 시에는 propTypes 사용을 빼먹기도 했는데 이번에는 감사하며(?) 사용했습니다. 😂
타입 체크는 협업과 유지보수에도 특히 도움이 될 것 같습니다. ㅎㅎ

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

타입 체크까지... 짱~~ 앞으로 진행될 타입스크립트 과제들이 기대가 되네요 🥰

Comment on lines 61 to 70
<SectionInput>
<input
type="text"
placeholder="type here ..."
value={inputText}
onChange={handleInputChange}
onKeyDown={handleInputKeyDown}
></input>
<span onClick={submitInput}>+</span>
</SectionInput>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 부분은 <SectionInput>styled.form으로 선언하고, <span> 부분을 <button type = 'submit'>(따로 type을 지정하지 않으면 default값이 submit으로 됩니다) 으로 지정하면 onSubmit함수 하나로 handling할 수 있을 것 같아요!

Suggested change
<SectionInput>
<input
type="text"
placeholder="type here ..."
value={inputText}
onChange={handleInputChange}
onKeyDown={handleInputKeyDown}
></input>
<span onClick={submitInput}>+</span>
</SectionInput>
<SectionInput> //styled.form으로 정의
<input
type="text"
placeholder="type here ..."
value={inputText}
onChange={handleInputChange}
onSubmit={handleSubmit}
/>
<button type="submit">+</button>
</SectionInput>

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 방법이 더 좋네요! 이렇게 수정해보겠습니다
용도에 맞는 태그를 적절히 활용하는 것으로 코드를 줄일 수 있다는 것 👍👍 앞으로 작업하면서 이 부분도 신경써야겠어요

Comment on lines 25 to 43
const handleInputKeyDown = (e) => {
if (e.key === 'Enter') {
submitInput();
}
};

const submitInput = () => {
if (inputText.trim()) {
const todoObj = {
text: inputText, // string
time: String(Date.now()), // string,
isDone: false, // boolean
};
setTodoList([...todoList, todoObj]);
setInputText('');

localStorage.setItem(TODOKEY, JSON.stringify([...todoList, todoObj]));
}
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아래 comment와 연결되는 수정사항입니다! (웹에서 수정해서 제대로 돌아갈지는 모르겠어요ㅠ)

Suggested change
const handleInputKeyDown = (e) => {
if (e.key === 'Enter') {
submitInput();
}
};
const submitInput = () => {
if (inputText.trim()) {
const todoObj = {
text: inputText, // string
time: String(Date.now()), // string,
isDone: false, // boolean
};
setTodoList([...todoList, todoObj]);
setInputText('');
localStorage.setItem(TODOKEY, JSON.stringify([...todoList, todoObj]));
}
};
const handleSubmit = () => {
if (inputText.trim()) {
const todoObj = {
text: inputText, // string
time: String(Date.now()), // string,
isDone: false, // boolean
};
setTodoList([...todoList, todoObj]);
setInputText('');
localStorage.setItem(TODOKEY, JSON.stringify([...todoList, todoObj]));
}
};

Comment on lines 10 to 11
setIsVisibleModal, // 컴포넌트 재사용성이 낮아지는 것 같은데.. 우짜지
setSelectedTodo, // 컴포넌트 재사용성이 낮아지는 것 같은데.. 우짜지
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

재사용성이 낮아진다는것...이 뭔지 저도 잘 모르겠어서 이번주 스터디까지 한번 공부해보고 얘기 해보면 좋을 것 같습니다...ㅎㅎ 댓글로 다른분들이 알려주시면 공부 해가도록 할게요 😄

Comment on lines +95 to +107
{isVisibleModal && (
<ModalWrapper>
<Modal>
<span>이 할 일을 지울까요?</span>
<div>
<button onClick={removeTodo}>네</button>
<button onClick={() => setIsVisibleModal(false)}>취소</button>
</div>
</Modal>
</ModalWrapper>
)}
</Wrapper>
);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저어는.... 이거 왜 안되는지 모르겠어서 if문을 막 덕지덕지 발라놨는데 이렇게 쓰는게 훨씬 깔끔한 것 같아요

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

boolean 타입의 변수를 적절히 활용하면 코드가 깔끔하면서 논리도 간단해지는 것 같아요.
저도 더 잘 사용하는 방법 꾸준히 배우고 공유하겠습니다~!

`;

let Modal = styled.div`
width: 15rem;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rem을 쓰는게 UX적으로 좋다고 하는데 전 익숙하지가 않아서 쓰기 어려운 것 같아요 ㅠㅠ 혹시 쓰실 때 편한 팁이 있다면 알려주시면 공부 많이 해보겠습니다!!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

사실 저도 아직 px 단위에 익숙해서 ceos 과제 하면서 rem을 최대한 사용해보고 있습니다 ㅠㅠ ㅎㅎ
괜찮은 자료 찾아보고 스터디때 들고 가겠습니닷

Copy link
Member

@kongnayeon kongnayeon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

안녕하세요 가은님~~ 프론트 운영진 강나연입니다 😻
코드가 깔끔해서 굉장히 리뷰하기 좋았습니다 ㅎ.ㅎ
타입스크립트 사용하셨던 흔적이 많이 보이는 코드였어요!
고민하시던 부분에 대해 코멘트를 남겨 뒀는데 참고해 주시면 좋을 것 같아요!
이번 과제도 수고 많으셨고 내일 스터디 시간에 봬요!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ㅋㅋㅋㅋㅋㅋ 파비콘 보자마자 리뷰하러 왔는데 역씨... 😸

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

key를 따로 관리하는 방식 좋네요 🥰

Comment on lines +49 to +56
ListContainer.propTypes = {
title: PropTypes.string,
todoList: PropTypes.array,
setTodoList: PropTypes.func,
isDone: PropTypes.bool,
setIsVisibleModal: PropTypes.func,
setSelectedTodo: PropTypes.func,
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

타입 체크까지... 짱~~ 앞으로 진행될 타입스크립트 과제들이 기대가 되네요 🥰

Comment on lines 10 to 11
setIsVisibleModal, // 컴포넌트 재사용성이 낮아지는 것 같은데.. 우짜지
setSelectedTodo, // 컴포넌트 재사용성이 낮아지는 것 같은데.. 우짜지
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

좋은 방법인진 모르겠지만... setIsVisibleModal, setSelectedTodo 등의 함수를 사용하는 Listcontainer 컴포넌트의 부모 컴포넌트를 따로 만들고, ListContainer 컴포넌트에 prop으로 내려 주는 방법도 있을 것 같아요!

const ListContainer = ({ title, todoList, isDone, onToggleIsDone, onDeleteTodo }) => {
...
const ParentComponent = () => {
  const [isVisibleModal, setIsVisibleModal] = useState(false);
  const [selectedTodo, setSelectedTodo] = useState(null);
  const [todoList, setTodoList] = useState([]);

  const onToggleIsDone = (todo) => {
...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여러 페이지에서 재사용이 많이 되는 컴포넌트의 경우 이런식으로 분리해보면 좋을 것 같아요! 👍👍

Copy link

@oyatplum oyatplum left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

안녕하세요 이예지입니다!!😻
가은님 이번 주도 과제 하시느라 수고하셨어요~!!

코드 리뷰하면서 제가 더 많이 배우고 깨달은 게 많았던 것 같아요ㅎㅎㅎ 역시나 css는 너무 너무 깔끔하고 보기 편했습니다!!

특히 propTypes 쓰신 것 보고 다음 주 과제가 너무 기대되더라구요!! 저는 두렵기만 한데...😿 중복되는 코드 없이 최대한 간결하게 작성하려고 노력하신 것 같았습니당👏🏻👏🏻

너무 잘 봤고 고생하셨습니다!! 스타디 때 봬요~!~😳

@@ -2,42 +2,19 @@
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<link rel="icon" href="%PUBLIC_URL%/favicon.png" />

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

우와웅 저도 이건 처음 알았어요!! 좋은 정보 감사합니다💪🏻

});
setTodoList(tempList);

localStorage.setItem(TODOKEY, JSON.stringify(tempList));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저도 string으로 사용했었는데 변수로 만들어 두는 것이 더 좋겠네요!! 이렇게 또 배워갑니다ㅠㅠ👏🏻👏🏻👏🏻

Comment on lines +7 to +17
body {
width: 100vw;
height: 100vh;
margin: 0;
background-color: lavender;

font-family: 'Pretendard-Regular';
font-weight: 400;
font-style: normal;
font-size: 1rem;
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

가은님은 css 단위를 항상 잘 쓰시는 것 같아요!! vw부터 vh, rem 등등.. 저는 px, % 등의 익숙한 단위들만 사용하다 보니 종종 불편할 때가 있더라구요ㅠㅠ 가은님처럼 상황에 맞는 적절한 단위를 사용하는 것이 더 효율적일 것 같네요!!!👏🏻👏🏻

src/index.js Outdated
Comment on lines 2 to 11
import ReactDOM from 'react-dom/client';
import App from './App';

ReactDOM.render(
import './index.css';

ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
); No newline at end of file
</React.StrictMode>
);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저는 StrictMode를 사용하니까 렌더링이 2번씩(console.log()가 2번씩) 되더라구요!! 혹시 가은님은 이렇게 해도 괜찮으셨나요??
StrictMode는 잠재적인 여러 문제들을 알려주는 장점이 있지만 개발 모드에서만 활성화되고 빌드가 된 후의 프로젝트에서는 비활성화 된다고 해요!!
그래서 빌드할 때 StrictMode를 남겨두는 것이 좋을지, 지우는 것이 좋을지 고민되던데...
혹시 가은님은 어떤 방법이 효율적인지 알고 계시다면 알려주시면 감사하겠습니다!!
이건 제가 참고했던 자료들입니다!!ㅎㅎㅎ 참고자료1 참고자료2

Comment on lines 21 to 29
const handleInputChange = (e) => {
setInputText(e.target.value);
};

const handleInputKeyDown = (e) => {
if (e.key === 'Enter') {
submitInput();
}
};

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저는 이번 코드 리뷰하면서 이벤트 핸들러의 이름을 보통 handle + 대상 + 동작의 형식으로 짓는다는 것을 처음 알게 되었는데 가은님은 역시 잘 지키면서 해주셨군요!!! 최고최고!!😆

Comment on lines 33 to 37
const todoObj = {
text: inputText, // string
time: String(Date.now()), // string,
isDone: false, // boolean
};

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Date.now()를 string type으로 해주신 이유가 궁금합니당!!!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Time 정보를 각 리스트의 id로 사용하고, 이 id값(->string) 을 다시 가져와 비교하는 경우가 있어 타입을 변경해주었습니다!
그런데 지금 답변드리다보니 그냥 == 을 사용하는 게 나았겠다는 생각이 드네요,, 이 부분 수정해봐야겠어요 감사합니다!

Comment on lines +95 to +105
{isVisibleModal && (
<ModalWrapper>
<Modal>
<span>이 할 일을 지울까요?</span>
<div>
<button onClick={removeTodo}>네</button>
<button onClick={() => setIsVisibleModal(false)}>취소</button>
</div>
</Modal>
</ModalWrapper>
)}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

우와 이렇게 지우기 전에 확인 창을 띄워주는 아이디어 너무 좋은 것 같아요!!!👏🏻👏🏻👏🏻

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants