Conversation
ZUITOPIA
left a comment
There was a problem hiding this comment.
고생하셨습니다 지수님! 컴포넌트 분리와 emotion css 사용에 집중하신게 눈에 보여요 👍
현재 배포된 기능 상, todo의 양이 무척 많아지게 된다면 창 전체 스크롤을 끊임없이 내려야하는 일이 생길 수도 있겠다는 생각이 들었는데, 이 부분을 조금 더 개선해보는 것은 어떨까 하는 추가적인 의견을 하나 드려봅니다!
|
|
||
| function TodoButton({ onClick, children }) { | ||
| return ( | ||
| <button css={buttonStyle} onClick={onClick}> |
There was a problem hiding this comment.
onClick 함수 이름으로 동작이 어떤 것인지 예측 가능하게 작성해주시면 더 좋을 것 같습니다 🤩
| }; | ||
|
|
||
| return ( | ||
| <div css={containerStyle}> |
| return savedTodos ? JSON.parse(savedTodos) : []; // 저장된 값이 있으면 파싱하여 사용, 없으면 빈 배열 | ||
| }); | ||
|
|
||
| useEffect(() => { |
There was a problem hiding this comment.
useEffect에서 함수를 사용할 경우를 대비하여 변수, 함수 선언 맨 마지막에 위치하도록 미리 습관을 들여보는 것은 어떨까요 ?!
| `; | ||
|
|
||
| function TodoInput({ addTodo }) { | ||
| const [input, setInput] = useState(''); // 입력 값을 관리하기 위한 상태 선언 |
There was a problem hiding this comment.
어떤 것을 입력하여 상태 관리할 것인지 알기 쉽도록 변수의 이름을 더 상세하게 적어주시면 좋을 것 같아요! ex. inputTodo
|
|
||
| // 새 할 일을 추가하는 함수 | ||
| const addTodo = (text) => { | ||
| setTodos(todos.concat({ text, completed: false })); // 새로운 할 일을 기존 할 일 리스트에 추가 |
There was a problem hiding this comment.
boolean 값을 저장하는 변수는 맞다, 아니다 2가지 상태만 나타내므로 더욱 더 네이밍에 신경써주는 것이 좋습니다! completed 보다 isCompleted 와 같은 의문문 형식의 이름을 더 많이 사용합니다 🤩
There was a problem hiding this comment.
저도 동의합니다 !! boolean 값을 갖는 변수명은� 보통 is를 접두어로 사용하죠 ~!
| // 개별 Todo 항목을 나타내는 컴포넌트 | ||
| function TodoItem({ todo, index, deleteTodo, toggleTodo }) { | ||
| return ( | ||
| <div css={[itemStyle, todo.completed ? completedStyle : null]}> |
There was a problem hiding this comment.
이 코드와 같은 경우에서도 isCompleted 를 사용하면, "완료 시에는 completeStyle을 사용하고 아직 완료하지 않았다면 아무런 스타일을 적용하지 않는구나" 라고 명확하게 이해하기가 쉬워집니다!
There was a problem hiding this comment.
조건이 false일 때 null을 리턴하기보다는 && 연산자를 사용해 볼 수 있을 것 같아요~
| <div css={[itemStyle, todo.completed ? completedStyle : null]}> | |
| <div css={[itemStyle, todo.completed && completedStyle]}> |
| `; | ||
|
|
||
| function TodoList({ todos, deleteTodo, toggleTodo }) { | ||
| const pendingTodos = todos.filter((todo) => !todo.completed); // 완료되지 않은 할 일만 필터링 |
| /** @jsxImportSource @emotion/react */ | ||
| import { useState, useEffect } from 'react'; | ||
| import { css } from '@emotion/react'; | ||
| import TodoInput from './components/TodoInput'; |
corinthionia
left a comment
There was a problem hiding this comment.
안녕하세요 지수 님!
컴포넌트 이름을 직관적으로 잘 지어 주시고, 분리도 잘해 주셔서 리뷰하기가 편했습니다 🙌
이번주 미션도 고생하셨습니다 👍🏻
| import { css } from '@emotion/react'; | ||
| import TodoInput from './components/TodoInput'; | ||
| import TodoList from './components/TodoList'; | ||
| import TodoHeader from './components/TodoHeader'; |
There was a problem hiding this comment.
컴포넌트 이름도 직관적으로 지어 주셔서 아주 좋습니다!
| // 특정 인덱스의 할 일의 완료 상태를 토글하는 함수 | ||
| const toggleTodo = (index) => { | ||
| setTodos(todos.map((todo, i) => | ||
| i === index ? { ...todo, completed: !todo.completed } : todo |
There was a problem hiding this comment.
특정 아이템을 토글/삭제 하려고 할 때, 다른 아이템이 토글/삭제 되는 경우가 있는데, 이 경우 배열 내 요소가 달라지면서 인덱스 값도 함께 바뀌게 되어서 발생하는 문제 같아요!
| // 개별 Todo 항목을 나타내는 컴포넌트 | ||
| function TodoItem({ todo, index, deleteTodo, toggleTodo }) { | ||
| return ( | ||
| <div css={[itemStyle, todo.completed ? completedStyle : null]}> |
There was a problem hiding this comment.
조건이 false일 때 null을 리턴하기보다는 && 연산자를 사용해 볼 수 있을 것 같아요~
| <div css={[itemStyle, todo.completed ? completedStyle : null]}> | |
| <div css={[itemStyle, todo.completed && completedStyle]}> |
| {todos.map((todo, index) => ( | ||
| <TodoItem | ||
| key={index} |
There was a problem hiding this comment.
key 값으로 map()의 index를 사용하는 방법은 바람직하지 않습니다!
리스트 항목의 순서가 바뀌거나 항목이 추가/삭제될 때, 각 항목에 대응되는 index 값이 변경되기 때문에 이전 key와 새로운 key가 달라지게 됩니다. 이는 곧 React가 해당 항목을 새롭게 렌더링해야 한다고 판단하여 불필요한 리렌더링을 초래할 수 있습니다.
즉, key를 사용하는 이유가 불필요한 리렌더링의 방지인데, 이 경우 오히려 불필요한 리렌더링이 발생할 수 있다는 것입니다!
참고자료 - React 공식문서 key 규칙
참고자료 - 리액트에서 key에 index를 넣으면 안 되는 '진짜' 이유
안녕하세요, 유레카 1기 프론트엔드 이지수입니다.🙂
지난번 미션과 다르게 React를 사용해 진행하게 되었는데, 컴포넌트 분리부터 쉽지않아서 걱정이 많았던 미션이였습니다.😭
처음에는 React의 구조에 익숙하지 않아 헷갈렸지만, 실제로 작업하면서 코드의 재사용성과 유지보수 측면에서 큰 장점을 느꼈던 미션이였습니다.특히 바닐라JS로 작성했던 코드보다 훨씬 더 효율적으로 컴포넌트를 관리할 수 있었고, 상태 관리 역시 한결 수월해졌습니다. React를 다루면서 프레임워크의 진가를 체감할 수 있었던 좋은 기회였습니다.
리액트를 사용함에 있어서 아직 부족한 부분이 많지만 앞으로의 미션을 수행하면서 더 성장하겠습니다!!!
📍알게된 부분
1.패키지 관리 도구 yarn과 vite 사용법을 배울 수 있었습니다.2.emotion 사용법
JavaScript에서 직접 CSS를 작성할 수 있는 라이브러리
컴포넌트의
cssprop으로 전달하여 스타일을 적용객체나 템플릿 리터럴 형식으로 스타일을 작성 가능
3.localStorage를 이용한 데이터 저장 및 불러오기
데이터 저장: 데이터를 추가하거나 변경할 때
localStorage.setItem(key, JSON.stringify(data))를 사용데이터 불러오기: 페이지가 로드되거나 초기 상태를 설정할 때
JSON.parse(localStorage.getItem(key))로 데이터 가져옴📍Key question
1.지난주 미션과 비교했을 때, React로 구현하는 과정에서 어떤 점이 더 편리하거나 복잡했나요?
2.React의 Virtual DOM(가상 돔)이란 무엇이고, 이를 사용했을 때의 장점은 무엇이 있나요?
3.React에서 state와 props는 무엇이고 어떻게 사용하나요?
State: useState 훅 사용, setState( )
Props: 자식 컴포넌트 props 읽기만함
함수의 매개변수 혹은 this.props로 접근
4.React에서 컴포넌트를 분리하는 기준은 무엇일까요?
📍개선하고 싶은 부분
📍배포
vercel을 통해 배포하였습니다!https://react-todo-jissssu.vercel.app/