-
Notifications
You must be signed in to change notification settings - Fork 13
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
[3주차] 주효정 미션 제출합니다. #15
base: master
Are you sure you want to change the base?
Changes from 37 commits
a96be62
13dce4a
3426754
730aa49
1dfcca7
72e52c3
2fd507f
2508a13
c8638ea
66843a2
c0530ec
4742cf7
e78f1ab
73a2035
57c76d1
c6f5f52
f795be3
5690951
f30b495
6e6256c
22d1f3d
8f38c5e
a971121
3ba7e60
6edb893
9b3b9e9
3d0c45a
f813526
ed12088
5404fc6
a1514c9
8eb76cc
6c10362
0aaf39f
4024ce2
90f7462
c950615
69ad840
dbec7e7
69f52da
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import { useEffect, useCallback, useContext } from "react"; | ||
import styled from "styled-components"; | ||
import { TodoInputForm, TodoList, DoneList } from "components"; | ||
import { TodoContext } from "contexts"; | ||
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. contexts에서 index.tsx에서 따로 export 해온게 이부분에서 더 깔끔하게 보이기 위해서라고 이해하면 될까요?? 혹시 다른 이유가 또 있을까요?? 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. 특별한 이유는 없고 한 폴더에서 여러 컴포넌트를 import 할 때 한 줄로 깔끔하게 import하기 위해서 자주 사용했습니다.. |
||
import { ITodoItem } from "interface"; | ||
|
||
const App = () => { | ||
const { todoList, doneList } = useContext(TodoContext); | ||
|
||
// save to localStorage | ||
const _saveLocalStorage = useCallback( | ||
(type: string, list: Array<ITodoItem>): void => { | ||
localStorage.setItem(type, JSON.stringify(list)); | ||
}, | ||
[], | ||
); | ||
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. 이 부분은 Hooks 내부에 정의할 필요는 따로 없을 것 같네요 ㅎㅎ 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가 변할 때마다 localStorage에 list 저장 | ||
useEffect(() => { | ||
_saveLocalStorage("todoList", todoList); | ||
}, [todoList, _saveLocalStorage]); | ||
useEffect(() => { | ||
_saveLocalStorage("doneList", doneList); | ||
}, [doneList, _saveLocalStorage]); | ||
|
||
return ( | ||
<Container> | ||
<Box> | ||
<TitleContents> | ||
<TodoTitle>📝 투두리스트</TodoTitle> | ||
</TitleContents> | ||
<TodoInputForm /> | ||
<TodoList /> | ||
<DoneList /> | ||
</Box> | ||
</Container> | ||
); | ||
}; | ||
|
||
const TitleContents = styled.section``; | ||
const TodoTitle = styled.h2` | ||
padding-left: 20px; | ||
`; | ||
const Container = styled.div` | ||
height: 100vh; | ||
display: flex; | ||
justify-content: center; | ||
align-items: center; | ||
`; | ||
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. 어쩐지 네이밍이 마음에 안 들더라구요.. 알려주셔서 감사합니다! |
||
const Box = styled.main` | ||
width: 350px; | ||
height: 600px; | ||
background-color: white; | ||
border-radius: 20px; | ||
box-shadow: 1px 1px 30px grey; | ||
`; | ||
|
||
export default App; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import { useContext, useCallback } from "react"; | ||
import styled from "styled-components"; | ||
import TodoItem from "./TodoItem"; | ||
import { TodoContext } from "contexts"; | ||
|
||
const DoneList = () => { | ||
const { doneList, dispatch } = useContext(TodoContext); | ||
|
||
// todo item 추가 | ||
const _addTodoList = useCallback( | ||
(todo: string): void => { | ||
dispatch({ | ||
type: "ADD_TODO", | ||
todo: { text: todo }, | ||
}); | ||
}, | ||
[dispatch], | ||
); | ||
|
||
// done item 삭제 | ||
const _deleteDoneList = useCallback( | ||
(idx: number): void => { | ||
dispatch({ | ||
type: "DELETE_DONE", | ||
idx, | ||
}); | ||
}, | ||
[dispatch], | ||
); | ||
|
||
return ( | ||
<TodoContents> | ||
<h3>DONE ({doneList.length})</h3> | ||
<ul> | ||
{doneList.map(({ text }, idx) => ( | ||
<TodoItem | ||
key={idx} | ||
type="done" | ||
todo={text} | ||
idx={idx} | ||
deleteCurrentList={_deleteDoneList} | ||
addToggleList={_addTodoList} | ||
/> | ||
))} | ||
</ul> | ||
</TodoContents> | ||
); | ||
}; | ||
|
||
const TodoContents = styled.section` | ||
padding: 0 20px; | ||
`; | ||
|
||
export default DoneList; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import React, { useCallback, useContext } from "react"; | ||
import styled from "styled-components"; | ||
import { TodoContext } from "contexts"; | ||
import { useInput } from "hooks"; | ||
|
||
const TodoInputForm = () => { | ||
const { dispatch } = useContext(TodoContext); | ||
const { text, _handleTextChange, _resetText } = useInput(""); | ||
|
||
// todo item 추가 | ||
const _addTodoItem = useCallback( | ||
(e: React.FormEvent): void => { | ||
e.preventDefault(); | ||
|
||
if (text.trim()) { | ||
// list에 todo item 추가 | ||
dispatch({ | ||
type: "ADD_TODO", | ||
todo: { text }, | ||
}); | ||
} | ||
_resetText(); | ||
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. 이 부분은 앞서 말씀드린 useTodo 훅에 넣어도 될 것 같네요! const { addTodo } = useTodo()
const handleTodoInputChange = (event: React.FormEvent) => {
addTodo({text: event.target.value})
}
// ... addTodo는 useTodo내에서 구현 이렇게 하면 todoInputForm의 이벤트 처리 로직과 todo 상태 변경 로직의 분리를 달성할 수 있습니다. 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. 넵 커스텀 훅에 적용해보도록 하겠습니다~! |
||
}, | ||
[text, _resetText, dispatch], | ||
); | ||
|
||
return ( | ||
<TodoInputItems onSubmit={_addTodoItem}> | ||
<TodoInput | ||
placeholder="할 일을 입력하세요" | ||
value={text} | ||
onChange={_handleTextChange} | ||
/> | ||
<TodoInputBtn type="submit">+</TodoInputBtn> | ||
</TodoInputItems> | ||
); | ||
}; | ||
|
||
const TodoInputItems = styled.form` | ||
display: flex; | ||
justify-content: center; | ||
align-items: center; | ||
padding-bottom: 15px; | ||
border-bottom: 1px solid lightgrey; | ||
`; | ||
const TodoInput = styled.input` | ||
border: 1px solid lightgrey; | ||
border-radius: 10px; | ||
padding: 15px; | ||
width: 230px; | ||
:focus { | ||
outline: none; | ||
transition: 0.2s; | ||
box-shadow: 0px 0px 5px lightgrey; | ||
} | ||
`; | ||
const TodoInputBtn = styled.button` | ||
background: none; | ||
border: none; | ||
font-size: 30px; | ||
margin-left: 10px; | ||
cursor: pointer; | ||
border-radius: 30px; | ||
:hover { | ||
color: grey; | ||
transition: 0.2s; | ||
} | ||
`; | ||
|
||
export default TodoInputForm; |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,67 @@ | ||||||||||||||||||||||||||||||
import React, { useCallback } from "react"; | ||||||||||||||||||||||||||||||
import styled, { css } from "styled-components"; | ||||||||||||||||||||||||||||||
import { ITodoItemProps } from "interface"; | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
const TodoItem = ({ | ||||||||||||||||||||||||||||||
type, | ||||||||||||||||||||||||||||||
todo, | ||||||||||||||||||||||||||||||
idx, | ||||||||||||||||||||||||||||||
deleteCurrentList, | ||||||||||||||||||||||||||||||
addToggleList, | ||||||||||||||||||||||||||||||
}: ITodoItemProps) => { | ||||||||||||||||||||||||||||||
Comment on lines
+5
to
+11
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
보통은 이런 식으로 직접 컴포넌트를 타이핑해준답니다. 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 <-> done | ||||||||||||||||||||||||||||||
const _toggleTodo = useCallback((): void => { | ||||||||||||||||||||||||||||||
// toggle된 리스트에 item 추가 | ||||||||||||||||||||||||||||||
addToggleList(todo); | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
// 현재 리스트에서 item 삭제 | ||||||||||||||||||||||||||||||
deleteCurrentList(idx); | ||||||||||||||||||||||||||||||
}, [addToggleList, todo, deleteCurrentList, idx]); | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
// delete item | ||||||||||||||||||||||||||||||
const _deleteTodo = useCallback((): void => { | ||||||||||||||||||||||||||||||
deleteCurrentList(idx); | ||||||||||||||||||||||||||||||
}, [idx, deleteCurrentList]); | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
return ( | ||||||||||||||||||||||||||||||
<ListItem> | ||||||||||||||||||||||||||||||
<ListToggleItem onClick={_toggleTodo}> | ||||||||||||||||||||||||||||||
<span>{type === "todo" ? "□" : "✔"}</span> | ||||||||||||||||||||||||||||||
<ListItemText type={type}>{todo}</ListItemText> | ||||||||||||||||||||||||||||||
</ListToggleItem> | ||||||||||||||||||||||||||||||
<TodoDeleteBtn src="bin.png" alt="delete-btn" onClick={_deleteTodo} /> | ||||||||||||||||||||||||||||||
</ListItem> | ||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
const TodoDeleteBtn = styled.img` | ||||||||||||||||||||||||||||||
width: 14px; | ||||||||||||||||||||||||||||||
padding-left: 5px; | ||||||||||||||||||||||||||||||
cursor: pointer; | ||||||||||||||||||||||||||||||
opacity: 0; | ||||||||||||||||||||||||||||||
`; | ||||||||||||||||||||||||||||||
const ListItem = styled.li` | ||||||||||||||||||||||||||||||
margin-bottom: 13px; | ||||||||||||||||||||||||||||||
:hover { | ||||||||||||||||||||||||||||||
${TodoDeleteBtn} { | ||||||||||||||||||||||||||||||
opacity: 1; | ||||||||||||||||||||||||||||||
transition: 0.1s; | ||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||
Comment on lines
+46
to
+49
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. styled-components의 고급 기능을 잘 활용하셨네요!
Comment on lines
+43
to
+49
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. hover 안에 다른 요소를 넣을 수 도 있군요..! 앞으로 저도 자주 쓰게 될 것 같습니다. |
||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||
`; | ||||||||||||||||||||||||||||||
const ListToggleItem = styled.section` | ||||||||||||||||||||||||||||||
display: inline; | ||||||||||||||||||||||||||||||
cursor: pointer; | ||||||||||||||||||||||||||||||
`; | ||||||||||||||||||||||||||||||
const ListItemText = styled.span<{ type: "todo" | "done" }>` | ||||||||||||||||||||||||||||||
font-size: 15px; | ||||||||||||||||||||||||||||||
padding-left: 5px; | ||||||||||||||||||||||||||||||
${({ type }) => | ||||||||||||||||||||||||||||||
type === "done" && | ||||||||||||||||||||||||||||||
css` | ||||||||||||||||||||||||||||||
text-decoration: line-through; | ||||||||||||||||||||||||||||||
color: lightgrey; | ||||||||||||||||||||||||||||||
`} | ||||||||||||||||||||||||||||||
`; | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
export default React.memo(TodoItem); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import { useContext, useCallback } from "react"; | ||
import styled from "styled-components"; | ||
import TodoItem from "./TodoItem"; | ||
import { TodoContext } from "contexts"; | ||
|
||
const TodoList = () => { | ||
const { todoList, dispatch } = useContext(TodoContext); | ||
|
||
// done item 추가 | ||
const _addDoneList = useCallback( | ||
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. 처음에는 변수명과 함수를 구분하기 위해 사용했던게 습관이 되었던 것 같습니다. 그런데 앞에 정시원 멘토님이 조언해주신 말씀을 보고 찾아보니 private 함수 앞에 붙여주는 일종의 자바스크립트 컨벤션이더라구요! |
||
(todo: string): void => { | ||
dispatch({ | ||
type: "ADD_DONE", | ||
todo: { text: todo }, | ||
}); | ||
}, | ||
[dispatch], | ||
); | ||
|
||
// todo item 삭제 | ||
const _deleteTodoList = useCallback( | ||
(idx: number): void => { | ||
dispatch({ | ||
type: "DELETE_TODO", | ||
idx, | ||
}); | ||
}, | ||
[dispatch], | ||
); | ||
|
||
return ( | ||
<TodoContents> | ||
<h3>TO DO ({todoList.length})</h3> | ||
<ul> | ||
{todoList.map(({ text }, idx) => ( | ||
<TodoItem | ||
key={idx} | ||
type="todo" | ||
todo={text} | ||
idx={idx} | ||
deleteCurrentList={_deleteTodoList} | ||
addToggleList={_addDoneList} | ||
/> | ||
))} | ||
</ul> | ||
</TodoContents> | ||
); | ||
}; | ||
|
||
const TodoContents = styled.section` | ||
padding: 0 20px; | ||
border-bottom: 1px solid lightgrey; | ||
`; | ||
|
||
export default TodoList; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import TodoInputForm from "./TodoInputForm"; | ||
import TodoList from "./TodoList"; | ||
import DoneList from "./DoneList"; | ||
|
||
export { TodoInputForm, TodoList, DoneList }; |
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.
타입 라이브러리의 경우 dev-dependencies에 추가해주면 배포 때 번들 사이즈를 줄일 수 있을 것 같아요!
[https://ingorae.tistory.com/1754](참고 링크)
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.
오 처음 안 사실이네요! 앞으로 참고해서 사용하겠습니다!