-
Notifications
You must be signed in to change notification settings - Fork 8
[2주차] 이효린 미션 제출합니다. #7
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
base: main
Are you sure you want to change the base?
Changes from all commits
f77ec81
283fb0d
2084c35
88b2c19
b8dda23
84775e7
b078703
c93b636
c50916b
af732c8
fea26ee
85abe44
031827f
a7a470c
f85502f
f65969a
d957d87
0de0688
eaf3c16
779bed8
5fd92bc
29b4b6e
b835b2d
32fe0fd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| body { | ||
| margin: 0; | ||
| padding: 0; | ||
| box-sizing: border-box; | ||
| } | ||
|
|
||
| * { | ||
| box-sizing: border-box; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,8 +1,8 @@ | ||
| <!doctype html> | ||
| <!DOCTYPE html> | ||
| <html lang="en"> | ||
| <head> | ||
| <meta charset="UTF-8" /> | ||
| <link rel="icon" type="image/svg+xml" href="/vite.svg" /> | ||
| <link rel="icon" type="image/svg+xml" href="/public/redHeart.svg" /> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 디테일이 진짜 멋져요. 지나치기 쉬운데 이런 꼼꼼함을 배워야겠습니다.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 아이고 과찬이십니다 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 진짜 꼼꼼함 인정!!!저도 효린이 코드보고 많이 배웁니다!!!! |
||
| <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
| <title>React Todo</title> | ||
| </head> | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,6 +10,8 @@ | |
| "preview": "vite preview" | ||
| }, | ||
| "dependencies": { | ||
| "@emotion/react": "^11.13.3", | ||
| "eslint-plugin-emotion": "^11.0.0", | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. devDependencies에 추가하면 좋을 것 같습니다. |
||
| "react": "^18.3.1", | ||
| "react-dom": "^18.3.1" | ||
| }, | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,5 +1,54 @@ | ||||||||||||||||||
| /** @jsxImportSource @emotion/react */ | ||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 다음과 같이 vite.config 수정하는 것으로 babel pragma를 따로 쓰지 않아도 됩니다. export default defineConfig({
plugins: [
react({
jsxImportSource: '@emotion/react',
}),
],
});그리고 이게 왜 필요한건지 찾아보시는 것도 좋을 것 같습니다. |
||||||||||||||||||
| import { css } from '@emotion/react'; | ||||||||||||||||||
| import Header from './Components/Header'; | ||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 경우 디렉토리 이름이 소문자인 것이 좋겠네요.
Suggested change
|
||||||||||||||||||
| import { useEffect, useState } from 'react'; | ||||||||||||||||||
| import { getLocalStorage } from './utils/getLocalStorage'; | ||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. utils로 따로 분리한 부분! 진짜 깔끔하고 제가 다음번에 꼭해야겠다고 생각했던 부분인데 또 한번 배우네요! |
||||||||||||||||||
| import List from './Components/List'; | ||||||||||||||||||
|
|
||||||||||||||||||
| function App() { | ||||||||||||||||||
| return <div>React Todo</div>; | ||||||||||||||||||
| const [todoList, setTodoList] = useState(getLocalStorage() || []); | ||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 로컬스토리지 관련 코드를 util 함수로 분리하니 훨씬 깔끔하네요 👍🏻 |
||||||||||||||||||
| useEffect(() => { | ||||||||||||||||||
| if (getLocalStorage() === null) { | ||||||||||||||||||
| localStorage.setItem('todo', JSON.stringify([])); | ||||||||||||||||||
| } | ||||||||||||||||||
| }, []); | ||||||||||||||||||
|
Comment on lines
+9
to
+14
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 초기 로컬스토리지 값은 undefined라 의미가 없는 코드일 것 같네요. |
||||||||||||||||||
| const notDoneTodoList = todoList.filter((todo) => todo.done === false); | ||||||||||||||||||
| const doneTodoList = todoList.filter((todo) => todo.done === true); | ||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 그냥 Done기능 todoList 기능 다 작성했던 제가 하고 싶었던 코드예요..ㅠㅠㅠ 엄청 깔끔하고... 다음엔 꼭 이렇게 작성해보고 싶어요.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 과분한 칭찬 너무 감사합니다 .. 🥹 js의 Array 메서드는 공부해두면 항상 도움이 되는 것 같아요 !
Comment on lines
+10
to
+16
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. useEffect를 활용하여 로컬 스터리지 초기화 처리 저도 적용해보겠습니다! 직관적인 변수,함수명 제가 잘 못하는 부분인데 참고하겠습니다! |
||||||||||||||||||
| return ( | ||||||||||||||||||
| <div | ||||||||||||||||||
| css={css({ | ||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||||||||||||||
| width: '100vw', | ||||||||||||||||||
| height: '100vh', | ||||||||||||||||||
| color: 'black', | ||||||||||||||||||
| display: 'flex', | ||||||||||||||||||
| justifyContent: 'center', | ||||||||||||||||||
| alignItems: 'center', | ||||||||||||||||||
| background: 'linear-gradient(pink,skyblue)', | ||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 색상이 아주 예쁘네요 👍🏻 |
||||||||||||||||||
| })} | ||||||||||||||||||
| > | ||||||||||||||||||
| <div | ||||||||||||||||||
| css={css({ | ||||||||||||||||||
| width: '360px', | ||||||||||||||||||
| height: '600px', | ||||||||||||||||||
| backgroundColor: 'white', | ||||||||||||||||||
| borderRadius: '20px', | ||||||||||||||||||
| boxShadow: '0px 0px 25px rgba(0, 0, 0, 0.25)', | ||||||||||||||||||
| })} | ||||||||||||||||||
| > | ||||||||||||||||||
| <Header setTodoList={setTodoList} /> | ||||||||||||||||||
| <List | ||||||||||||||||||
| listName="📋 TO DO" | ||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이런 매직 스트링은 지양하는 것이 좋습니다. 상수로 분리해주세요.
Suggested change
|
||||||||||||||||||
| list={notDoneTodoList} | ||||||||||||||||||
| setTodoList={setTodoList} | ||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이렇게 setState 함수를 그대로 전달하면 비즈니스 로직을 관리하기가 더 어려워집니다. 하위 컴포넌트들에서 마음대로 수정할 수 있는 점, 책임이 전가되는 점, 유지보수 측면 등. ex) deleteTodo, addTodo ... 또한 이런 데이터를 조작하는 로직은 따로 분리하는 것이 좋겠습니다. -> useTodo() |
||||||||||||||||||
| /> | ||||||||||||||||||
| <List | ||||||||||||||||||
| listName="💿 DONE" | ||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 여기도 매직 스트림 |
||||||||||||||||||
| list={doneTodoList} | ||||||||||||||||||
| setTodoList={setTodoList} | ||||||||||||||||||
| /> | ||||||||||||||||||
| </div> | ||||||||||||||||||
| </div> | ||||||||||||||||||
| ); | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| export default App; | ||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| /** @jsxImportSource @emotion/react */ | ||
| import { css } from '@emotion/react'; | ||
| import { deleteFromLocalStorage } from '../utils/deleteFromLocalStorage'; | ||
| import { getLocalStorage } from '../utils/getLocalStorage'; | ||
|
|
||
| export const DeleteButton = ({ id, setTodoList }) => { | ||
| return ( | ||
| <div | ||
| css={css({ cursor: 'pointer' })} | ||
| onClick={() => { | ||
| deleteFromLocalStorage(id); | ||
| setTodoList(getLocalStorage()); | ||
|
Comment on lines
+11
to
+12
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. LocalStorage를 왜 사용하는지 생각해보셨으면 좋겠습니다. LocalStorage를 데이터 원본 저장소처럼 활용하고 있는데요. 성능 면이나 관리 면에서 그냥 메모리에 있는 상태를 원본으로 두고 LocalStorage는 백업 용도로 사용하는 것이 좋겠습니다. 저라면 Todo State를 변경하고 그에 대한 Effect로 LocalStorage에 상태를 저장할 것 같네요. |
||
| }} | ||
| > | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. uills부분 한번 더 배우고갑니다! onClick이벤트 핸들러를 통해로컬 스토리지 적용한 부분 정말 간결하고 저도 이렇게 작성하고싶어요! |
||
| 🗑️ | ||
| </div> | ||
| ); | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| /** @jsxImportSource @emotion/react */ | ||
| import { css } from '@emotion/react'; | ||
| import { useEffect, useRef } from 'react'; | ||
| import { addToLocalStorage } from '../utils/addToLocalStorage'; | ||
| import { getLocalStorage } from '../utils/getLocalStorage'; | ||
|
|
||
| function Header({ setTodoList }) { | ||
| const inputRef = useRef(null); | ||
|
|
||
| const addTodo = () => { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 위에서 말한 addTodo 함수를 미리 만들어서 받아오고 여기는 handleKeyDown을 처리하는 것이 좋겠습니다. |
||
| const input = inputRef.current; | ||
| if (input.value === '') { | ||
| return; | ||
| } | ||
| addToLocalStorage(input.value); | ||
| input.value = ''; | ||
| inputRef.current.focus(); | ||
| setTodoList(getLocalStorage()); | ||
|
Comment on lines
+15
to
+18
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 위에서 말했듯이 addTodo 함수를 미리 받아와서 쓰는 것이 좋겠네요. |
||
| }; | ||
|
|
||
| useEffect(() => { | ||
| inputRef.current.focus(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍🏻👍🏻 |
||
| }, []); | ||
|
Comment on lines
+21
to
+23
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 속성에 autoFocus를 활용하면 필요 없는 로직입니다. |
||
|
|
||
| return ( | ||
| <div css={css({ height: '118px' })}> | ||
| <div css={css({ fontSize: '24px', margin: '18px 18px 0 18px' })}> | ||
| 📚 투두리스트 | ||
| </div> | ||
| <div | ||
| css={css({ | ||
| width: '100%', | ||
| height: '81px', | ||
| display: 'flex', | ||
| justifyContent: 'center', | ||
| alignItems: 'center', | ||
| gap: '10px', | ||
| borderBottom: 'solid 1px lightgray', | ||
| })} | ||
| > | ||
| <input | ||
| type="text" | ||
| ref={inputRef} | ||
| onKeyDown={(e) => { | ||
| if (e.nativeEvent.isComposing) return; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 오잉?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @Sieonn
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 그래서 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 헐 저도 오류는 처음보네요! 자바스크립트 자체 버그도 존재했다니ㅠㅠ저도 설명 듣고싶어요! |
||
| if (e.key === 'Enter') { | ||
| addTodo(); | ||
| } | ||
|
Comment on lines
+44
to
+48
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 로직이 퍼져있는데요 handleKeyDown을 만들고 그 안에서 관리를 하는 것이 좋을 것 같습니다. |
||
| }} | ||
| css={css({ | ||
| width: '288px', | ||
| height: '48px', | ||
| borderRadius: '15px', | ||
| border: 'solid 1px lightgray', | ||
| paddingLeft: '15px', | ||
| '&:focus': { | ||
| outline: 'none', | ||
| }, | ||
| })} | ||
| placeholder="할 일을 입력하세요" | ||
| /> | ||
| <div onClick={addTodo}>➕</div> | ||
| </div> | ||
| </div> | ||
| ); | ||
| } | ||
|
|
||
| export default Header; | ||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,35 @@ | ||||||||||
| /** @jsxImportSource @emotion/react */ | ||||||||||
| import { css } from '@emotion/react'; | ||||||||||
| import { TodoItem } from './TodoItem'; | ||||||||||
|
|
||||||||||
| function List({ list, setTodoList, listName }) { | ||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 할일/완료한일 컴포넌트를 따로 분리하지 않고 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 저도 추상화하는 부분을 어떻게해야할지가 너무 고민이였는데 효린님 코드보고 배우는거밖에 없는 것 같습니다!! |
||||||||||
| return ( | ||||||||||
| <div | ||||||||||
| css={css({ | ||||||||||
| height: '220px', | ||||||||||
| width: '100%', | ||||||||||
| padding: '18px 18px 0 18px', | ||||||||||
| borderBottom: listName == 'TO DO' ? 'solid 1px lightgray' : 'none', | ||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. listName이 실제로는 "📋 TO DO" 이런 식이라서 실제로는 적용이 안되고 있습니다. 역시 매직 스트링을 써서 문제가 되는 부분입니다. |
||||||||||
| })} | ||||||||||
| > | ||||||||||
| <div css={css({ fontSize: '18px', marginBottom: '15px' })}> | ||||||||||
| {listName} ({list.length}) | ||||||||||
| </div> | ||||||||||
| <div | ||||||||||
| css={css({ | ||||||||||
| width: '100%', | ||||||||||
| height: '156px', | ||||||||||
| overflowY: 'scroll', | ||||||||||
| display: 'flex', | ||||||||||
| flexDirection: 'column', | ||||||||||
| gap: '10px', | ||||||||||
| paddingRight: '20px', | ||||||||||
| })} | ||||||||||
| > | ||||||||||
| <TodoItem todoList={list} setTodoList={setTodoList} /> | ||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 제가 정말 구현하고 싶었던 내용이예요. 너무 깔끔해서 속이 시원합니다. 모양이 같은데 각각의 item과 섹션에만 영향을 줘야하는데 그런걸 처음에 다 설계를 하고 구현하시나요?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 엇 아닙니다 !! 제 커밋 내역을 보면 알겠지만 처음엔 별 생각 없이 구현하다가 동일한 구조가 보이면 그때 컴포넌트화 시키는 편인 것 같습니다 ! 사실 처음부터 설계하고 개발하는게 최고겠지만.. 아직 많이 부족하네요 😅 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 네이밍이 어색한 부분이 있네요. TodoItem인데 list를 전달해주고 있어서 그런 것 같습니다. 현재 TodoItem의 역할이 단순 map만 돌고 있는데. 차라리 다음과 같이 하는 게 좋겠습니다.
Suggested change
|
||||||||||
| </div> | ||||||||||
| </div> | ||||||||||
| ); | ||||||||||
| } | ||||||||||
|
|
||||||||||
| export default List; | ||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| /** @jsxImportSource @emotion/react */ | ||
| import { css } from '@emotion/react'; | ||
| import { DeleteButton } from './DeleteButton'; | ||
| import { updateFromLocalStorage } from '../utils/updateFromLocalStorage'; | ||
| import { getLocalStorage } from '../utils/getLocalStorage'; | ||
|
|
||
| export const TodoItem = ({ todoList, setTodoList }) => | ||
| todoList.map((todo, index) => ( | ||
|
Comment on lines
+7
to
+8
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 위에서 이어서, todo를 받고 todo에 대한 UI를 렌더링 하는 역할을 하는 것이 적절해보입니다. |
||
| <div | ||
| key={index} | ||
| css={css({ | ||
| display: 'flex', | ||
| justifyContent: 'space-between', | ||
| alignItems: 'center', | ||
| height: '20px', | ||
| width: '100%', | ||
| })} | ||
| > | ||
| <div | ||
| css={css({ | ||
| display: 'flex', | ||
| flexDirection: 'row', | ||
| textAlign: 'center', | ||
| alignItems: 'center', | ||
| width: '100%', | ||
| justifyContent: 'space-between', | ||
| })} | ||
| > | ||
| <div | ||
| css={css({ | ||
| cursor: 'pointer', | ||
| textDecoration: todo.done ? 'line-through' : 'none', | ||
|
Comment on lines
+29
to
+32
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 할 일 항목 완료여부에 따라 동적으로 설정하신 부분도 명확하게 보여서 너무 좋아요!!!!! |
||
| color: todo.done ? '#D3D3D3' : '#000', | ||
| textAlign: 'center', | ||
| })} | ||
| onClick={() => { | ||
| updateFromLocalStorage(todo.id); | ||
| setTodoList(getLocalStorage()); | ||
|
Comment on lines
+37
to
+38
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 현재 순서가 |
||
| }} | ||
| > | ||
| • {todo.todo} | ||
| </div> | ||
| <DeleteButton id={todo.id} setTodoList={setTodoList} /> | ||
| </div> | ||
| </div> | ||
| )); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,4 @@ | ||
| import { StrictMode } from 'react' | ||
| import { createRoot } from 'react-dom/client' | ||
| import App from './App.jsx' | ||
|
|
||
| createRoot(document.getElementById('root')).render( | ||
| <StrictMode> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이거 보고 StricMode가 뭔지 왜 자동으로 생성되어 감싸고 있는지 찾아보는 계기가 됐어요! 감사합니다. 휘발성 지식 획득~🦖
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 사실 StrictMode를 사용하면 개발 과정에서 발생하는 버그를 빠르게 잡을 수 있다는 장점이 있지만,, 전 디버깅하는 과정에서 console.log가 2회씩 찍히는게 불편해서 삭제했습니다 😞 StrictMode 관련 문서 추천드려용 ! (공식문서임) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 헐 저도 문서 같이 봐볼께요! 좋은 정보 감사합니다! |
||
| <App /> | ||
| </StrictMode>, | ||
| ) | ||
| import { createRoot } from 'react-dom/client'; | ||
| import App from './App.jsx'; | ||
| import '../index.css'; | ||
| createRoot(document.getElementById('root')).render(<App />); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| import { getLocalStorage } from './getLocalStorage'; | ||
|
|
||
| export const addToLocalStorage = (value) => { | ||
| const prevTodo = getLocalStorage(); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이렇게 따로 js를 분리해서 보니까 코드 보기가 더 편한 것 같네요!
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 사실 저도 이게 옳은 코드 스타일이다라고 말하긴 어렵지만 (아직은 이런 부분에 대한 확신이 없네요 ..🥲) 함수를 따로 js 파일로 빼서쓰니 깔끔하게 느껴져서 해봤씁니다 ! |
||
| const newTodo = prevTodo.concat({ | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| id: prevTodo.length + 1, | ||
| todo: value, | ||
| done: false, | ||
| }); | ||
| localStorage.setItem('todo', JSON.stringify(newTodo)); | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| import { getLocalStorage } from './getLocalStorage'; | ||
|
|
||
| export const deleteFromLocalStorage = (id) => { | ||
| const prevTodo = getLocalStorage(); | ||
| const newTodo = prevTodo.filter((todo) => todo.id !== id); | ||
| localStorage.setItem('todo', JSON.stringify(newTodo)); | ||
| alert('삭제되었습니다.'); | ||
| }; | ||
|
Comment on lines
+1
to
+8
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 함수 이름인 addToLocalStorage, deleteFromLocalStorage, getLocalStorage, updateFromLocalStorage가 각 함수의 역할을 명확하게 설명하고 있어서 코드를 이해하기 정말 쉬웠습니다! 함수 이름을 짓는 기준이 혹시 있으신가요? 저도 다음번에는 더 직관적이게 개선하고싶어요! |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| export const getLocalStorage = () => { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 만약 util 함수로 getLocalStorage라는 이름으로 함수를 만들고 싶었다면 key를 매개변수로 받아서 쓸수 있게 하는 것이 좋을 것 같습니다. 현재는 todo라는 관심사에 강하게 결합되어 있습니다. |
||
| return JSON.parse(localStorage.getItem('todo')); | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| import { getLocalStorage } from './getLocalStorage'; | ||
|
|
||
| export const updateFromLocalStorage = (id) => { | ||
| const prevTodo = getLocalStorage(); | ||
| const newTodo = prevTodo.map((todo) => { | ||
| return todo.id === id | ||
| ? { | ||
| ...todo, | ||
| done: !todo.done, | ||
| } | ||
| : todo; | ||
| }); | ||
| localStorage.setItem('todo', JSON.stringify(newTodo)); | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
emotion의
<Global>컴포넌트를 이용하여 Global style을 적용해 봐도 좋을 것 같아요!Emotion - Global Styles