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주차] 고윤정 미션 제출합니다. #2

Open
wants to merge 12 commits into
base: main
Choose a base branch
from

Conversation

jejukyj
Copy link
Member

@jejukyj jejukyj commented Sep 3, 2024

안녕하세요! LG U+ 유레카 프론트엔드 1기 고윤정입니다.

React로 미션을 진행함에 있어 걱정이 많았는데 어찌저찌 끝냈네요..🤣 바닐라JS로 만들었던 투두리스트를 React로 다시 개발해보니 확실히 차이점이 눈에 보였습니다. React에 익숙하지 않았을 땐 HTML, CSS, JS 파일을 따로 나눠서 관리하는게 더 편하다고 생각했는데 이번 미션을 진행해보니 마크업과 렌더링 로직이 같은 위치에 있는게 더 관리하기 쉽고 편리하다는 걸 느꼈습니다. 여기서 사람들이 React를 사용하는 이유를 확 깨달았던 것 같아요!

공식문서를 읽으며 React와 더 친해지도록 하겠습니다 화이팅+_+ !


📎 알게 된 부분

  • yarn과 Vite 사용법
  • Emotion 사용법
    • css() 함수 사용
    • 객체형({}) 또는 문자형(``)으로 넘김
    • 함수 반환 결과를 컴포넌트의 css라는 prop에 넘김
  • prop-types 유효성 검사코드
    • prop-types 라이브러리를 사용하여 prop의 데이터 type을 검사
  • localStorage 데이터 저장 및 출력 흐름

📎 개선하고 싶은 부분

  • state와 props 사용에 익숙해지기
  • CSS에 아이콘 적용해보기
  • 더 작은 단위로 커밋하기

📎 Key Questions

  • 지난주 미션과 비교했을 때, React로 구현하는 과정에서 어떤 점이 더 편리하거나 복잡했나요?

    • 🤩 localStorage에 데이터를 저장하고 그 값을 출력하는 과정이 JS와 비교했을 때 더 간단해졌습니다.
    • 🤩 컴포넌트 단위로 나누고 그 컴포넌트를 하나의 페이지에 넣으니 관리하기 편해졌습니다.
    • 🥲 Emotion 사용이 익숙하지 않아 CSS를 적용하는 시간이 오래 걸리고 방식도 더 복잡하게 느껴졌습니다.
  • React의 Virtual DOM(가상 돔)이란 무엇이고, 이를 사용했을 때의 장점은 무엇이 있나요?

    • 가상의 메모리 구조
    • 변경이 일어나는 부분만 적용 가능, 변경 사항을 실제 DOM 한번에 적용 ⇒ 렌더링 성능 향상
  • React에서 state와 props는 무엇이고 어떻게 사용하나요?

    • state : 컴포넌트의 변경 가능한 데이터 객체 → setState() 를 사용하여 값을 변경
    • props : 컴포넌트에 전달할 정보를 가지고 있는 객체 → 컴포넌트에 props 값 넣기
  • React에서 컴포넌트를 분리하는 기준은 무엇일까요?

    • 기능 단위로 분리
    • UI 요소 단위로 분리(ex. Header, Footer …)

📎 배포

https://jejukyj-react-todo.vercel.app/
스크린샷 2024-09-04 오전 10 28 54

Copy link
Member

@corinthionia corinthionia left a comment

Choose a reason for hiding this comment

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

안녕하세요 윤정 님~!
리뷰하다 보니 뭔가 일주일 만에 엄청나게 성장하신 것 같은데요?! 코드 가독성도 좋아지고 고심하여 코드를 작성하신 게 느껴졌습니다! 🤝 이번주 과제도 고생하셨습니다!! 👍🏻

@@ -10,6 +10,9 @@
"preview": "vite preview"
},
"dependencies": {
"@emotion/react": "^11.13.3",
"normalize.css": "^8.0.1",
Copy link
Member

Choose a reason for hiding this comment

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

normalize 좋습니다!

Copy link

@Sieonn Sieonn Sep 5, 2024

Choose a reason for hiding this comment

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

오? normalize.css는 처음봐서 찾아보니 정규화를 시켜주고 다른 브라우저로 보더라도 일정한 디자인을 볼 수 있도록 해주기위해서 사용한다고 하는데 좋은거 알아갑니다!!!

@@ -1,5 +1,85 @@
/** @jsxImportSource @emotion/react */
import { css } from '@emotion/react';
import 'normalize.css';
Copy link
Member

Choose a reason for hiding this comment

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

전역적으로 스타일을 적용하고 싶다면 Emotion의 Global 컴포넌트도 사용해 보세요!
참고 자료 - Emotion Global Styles

Comment on lines +9 to +20
const bodyStyle = css`
margin: 0;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-image: linear-gradient(
to bottom right,
rgb(247, 196, 218),
rgb(239, 239, 239)
);
`;
Copy link
Member

Choose a reason for hiding this comment

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

스타일 코드는 컴포넌트(App) 바깥에 작성해 주시면 가독성이 더 좋아질 것 같아요 😀

export default function App() {
   // 생략
}

const wrapper = css`
   // 생략
`;

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 +43 to +47
// 초기 상태를 localStorage에서 불러옴
const [todoList, setTodoList] = useState(() => {
const savedTodoList = localStorage.getItem('todoList');
return savedTodoList ? JSON.parse(savedTodoList) : [];
});
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

Choose a reason for hiding this comment

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

오 엄청 간결하면서도 동작이 잘 보여요!!
이름을 엄청 잘 지으시는 것 같어요

}, [todoList]);

return (
<div className="body" css={bodyStyle}>
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 +65 to +70
const AddTodoList = todoList.concat({
id: todoList.length,
text,
checked: false,
});
setTodoList(AddTodoList);
Copy link
Member

Choose a reason for hiding this comment

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

concat 메서드 사용 좋습니다! spread 연산자도 활용해 봅시다!

Suggested change
const AddTodoList = todoList.concat({
id: todoList.length,
text,
checked: false,
});
setTodoList(AddTodoList);
setTodoList(prev => [
...prev,
{
id: todoList.length,
text,
checked: false,
},
]);

}

// props 값 검증
InputBox.propTypes = {
Copy link
Member

Choose a reason for hiding this comment

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

나중에 타입스크립트도 잘하실 것 같아요 😉

// 항목 삭제
function onDelete(id) {
// 주어진 id와 일치하지 않는 항목들만 남김(일치하면 필터링 -> 해당 항목 삭제)
const updatedTodoList = todoList.filter((todoItem) => todoItem.id !== id);
Copy link
Member

Choose a reason for hiding this comment

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

👍🏻👍🏻

<span
className="span"
// 완료 여부에 따라 스타일 변경
css={todoItem.checked ? spanCheckedStyle : spanStyle}
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 +21 to +27
@font-face {
font-family: 'LINESeedKR-Rg';
src: url('https://fastly.jsdelivr.net/gh/projectnoonnu/[email protected]/LINESeedKR-Rg.woff2')
format('woff2');
font-weight: 400;
font-style: normal;
}
Copy link
Member

Choose a reason for hiding this comment

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

normalize.css를 비롯하여 이렇게 @font-face를 정의하는 부분도 글로벌 스타일로 적용해 보시면 좋을 것 같아요!

Copy link
Member

@ongheong ongheong left a comment

Choose a reason for hiding this comment

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

안녕하세요 윤정님! 2주차 미션에서 윤정님의 코드 리뷰를 맡게 된 심여은입니다!
깔끔하고 귀여운 스타일과 props의 타입까지 체크하는 꼼꼼한 코드 잘 읽어 보았습니다! 저는 styled-component의 방식으로 작성했는데, 윤정님은 emotion의 css()를 잘 적용해 주신 것 같아요!
저도 이번에 state와 props 사용이 어렵다고 느꼈는데, 같이 공식문서 읽어보면서 성장해봐요~~!!

Comment on lines +56 to +57
<div className="container" css={containerStyle}>
<h2 className="title" css={mainTitleStyle}>
Copy link
Member

Choose a reason for hiding this comment

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

emotion을 잘 적용해 주셔서 코드가 매우 간결하네요!

// + 버튼 클릭(form 제출)
function onClickButton() {
// 공백 입력 방지
if (text.trim() === '') return;
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

Choose a reason for hiding this comment

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

캬.. 공백 방지까지...디테일의 은혜가 끝이 없군요

Comment on lines +104 to +111
todoList: PropTypes.arrayOf(
PropTypes.shape({
id: PropTypes.number.isRequired,
text: PropTypes.string.isRequired,
}).isRequired
),
setTodoList: PropTypes.func.isRequired,
};
Copy link
Member

Choose a reason for hiding this comment

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

오 props 값을 이렇게 검증할 수 있군요! 새로 알아갑니다👀

setTodoList(AddTodoList);

setText(''); // input 값 초기화
inputRef.current.focus(); // 버튼 누른 후에도 input box에 자동 포커싱
Copy link
Member

Choose a reason for hiding this comment

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

useRef를 이용해서 input에 포커스를 주는 부분 새롭게 알아갑니다👀👀

Comment on lines +15 to +21
&::-webkit-scrollbar {
// 스크롤바 모양 변경
width: 4px;
}
&::-webkit-scrollbar-thumb {
border-radius: 2px; // 스크롤바 모서리 둥글게
background: rgb(255, 238, 245); // 스크롤바 색상 변경
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 +65 to +69
const AddTodoList = todoList.concat({
id: todoList.length,
text,
checked: false,
});
Copy link
Member

Choose a reason for hiding this comment

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

TodoList 배열 안의 객체를 식별하는 id를 length로 주신 이유가 있을까요? 만약 id가 같다면 원하지 않는 다른 객체가 수정될 수 있을 것 같아요! Date.now()와 같이 중복되지 않는 값을 id에 할당하면 좋을 것 같습니다!

Copy link

@Sieonn Sieonn left a comment

Choose a reason for hiding this comment

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

윤정님 그냥 화면만 봐도 깔끔 정갈 큐티입니다. 역시나 코드도 잘 정돈되어 있군요...!!!
제가 아이디어나 하고 싶은 기능을 쏟아내는 것은 잘하는데 깔끔하게 정리하고 효율적으로 사용하는것은 잘못하는데...많이 배우고 갑니다.. 최고...🩷

@@ -10,6 +10,9 @@
"preview": "vite preview"
},
"dependencies": {
"@emotion/react": "^11.13.3",
"normalize.css": "^8.0.1",
Copy link

@Sieonn Sieonn Sep 5, 2024

Choose a reason for hiding this comment

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

오? normalize.css는 처음봐서 찾아보니 정규화를 시켜주고 다른 브라우저로 보더라도 일정한 디자인을 볼 수 있도록 해주기위해서 사용한다고 하는데 좋은거 알아갑니다!!!

Comment on lines +43 to +47
// 초기 상태를 localStorage에서 불러옴
const [todoList, setTodoList] = useState(() => {
const savedTodoList = localStorage.getItem('todoList');
return savedTodoList ? JSON.parse(savedTodoList) : [];
});
Copy link

Choose a reason for hiding this comment

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

오 엄청 간결하면서도 동작이 잘 보여요!!
이름을 엄청 잘 지으시는 것 같어요

@@ -42,7 +42,7 @@ export default function InputBox({ todoList, setTodoList }) {
}
`;

const [text, setText] = useState('');
const [text, setText] = useState(''); // input에 입력한 값
const inputRef = useRef(null);
Copy link

Choose a reason for hiding this comment

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

저는 form을 사용하지 않아서 form을 사용했을 때 새로고침을 방지해야하는군요!! 배워갑니다!!!

// + 버튼 클릭(form 제출)
function onClickButton() {
// 공백 입력 방지
if (text.trim() === '') return;
Copy link

Choose a reason for hiding this comment

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

캬.. 공백 방지까지...디테일의 은혜가 끝이 없군요

@@ -79,8 +83,9 @@ export default function InputBox({ todoList, setTodoList }) {
ref={inputRef}
className="input-box"
placeholder="할일을 입력하세요"
Copy link

Choose a reason for hiding this comment

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

이런 placeholder하나만으로도 이 사이트의 정체성을 보여주는 것 같아요. 🦖 친절한 사이트...

const liStyle = css`
margin: 3px 0px 3px 0px;
`;

const checkBoxStyle = css`
Copy link

@Sieonn Sieonn Sep 5, 2024

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