Skip to content
This repository was archived by the owner on Sep 19, 2021. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 67 additions & 15 deletions components/todo-input.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,72 @@
import React from "react";
import React, { useState } from "react";
import styled from "styled-components";

export default function TodoInput() {
return (
<Wrapper>
리액트-투두
<br />
시간을 입력하는 칸
<br />
Todo를 입력하는 칸
</Wrapper>
);
export default function TodoInput({ addTodo }) {
const [thisTodo, setThisTodo] = useState({
})
Comment on lines +5 to +6

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
const [thisTodo, setThisTodo] = useState({
})
const [form, setForm] = useState({})
  1. thisTodo는 현재 입력중인 todo라는 역할을 잘 설명하지 못 하는 것 같아요!
  2. 빈 객체라서 줄바꿈 하지 않아도 될 것 같습니닿


const inputChangeHandler = (el) => {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

  1. 함수 이름을 지을때 동사가 맨 앞에 오도록 해주세요!
  2. el이 무엇의 약자인가요..?
Suggested change
const inputChangeHandler = (el) => {
const handleInputChange = (event) => {

const { name, value } = el.target;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

destructuring 잘 써주셨네요 👍


if (name === 'dueDate') {
if (value.length > 8) {
el.target.value = value.slice(0, 8);
return;
}
}

setThisTodo({
...thisTodo,
[name]: value
})
Comment on lines +11 to +21

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
if (name === 'dueDate') {
if (value.length > 8) {
el.target.value = value.slice(0, 8);
return;
}
}
setThisTodo({
...thisTodo,
[name]: value
})
setThisTodo({
...thisTodo,
[name]: name === 'dueDate' ? value.slice(0, 8) : value
})

이렇게 리팩토링할 수 있습니다!
slice(0, 8)는 현재 value의 length가 8 미만이면 그냥 안 자르고 그대로 반환하기 때문에 추가로 조건문을 작성할 필요가 없어용

}

return (
<Wrapper>
<TimeInput>
<p style={{"fontSize":"1.5rem","padding":"0px","margin":"0px"}}>시간</p>
<input style={{ "width": "80%", "borderWidth": "1px", "borderStyle": "solid", "borderColor": "rgb(97, 97, 97)", "borderImage": "initial", "padding": "0.5rem 0.8rem" }} name="dueDate" onChange={inputChangeHandler} type="number" placeholder="날짜를 입력하세요 (ex.20200404)"></input>
Comment on lines +26 to +28

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

styled-componet를 사용해주세요 ㅎ ㅠ

</TimeInput>
<ContentInput>
<p style={{"fontSize":"1.5rem","padding":"0px","margin":"0px"}}>TODO</p>
<textarea style={{"width":"80%","height":"30vh","resize":"none","borderWidth":"1px","borderStyle":"solid","borderColor":"rgb(97, 97, 97)","borderImage":"initial","padding":"0.5rem 0.8rem"}} name="content" onChange={inputChangeHandler} placeholder="할 일을 입력하세요"></textarea>
</ContentInput>
<button style={{"color":"white","backgroundColor":"rgb(97, 97, 97)","fontSize":"1.5rem","outline":"none","borderWidth":"initial","borderStyle":"none","borderColor":"initial","borderImage":"initial","padding":"0.5rem 1rem","borderRadius":"0.3rem"}} onClick={(() => {
addTodo(thisTodo);
})}>등록</button>
</Wrapper>
);
}

const TimeInput = styled.div`
width: 100%;
display: flex;
flex-direction: row;
-webkit-box-pack: justify;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 3rem;`

const ContentInput = styled.div`
width: 100%;
display: flex;
flex-direction: row;
-webkit-box-pack: justify;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 3rem;`

const Wrapper = styled.div`
border: solid 1px;
font-size: 18px;
flex: 1;
`;
width: 100%;
display: flex;
flex-direction: column;
-webkit-box-align: center;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
-webkit-box-align: center;

align-items: center;
height: 37rem;
flex: 1 1 0%;
border-width: 1px;
border-style: solid;
border-color: black;
border-image: initial;
Comment on lines +67 to +70

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
border-width: 1px;
border-style: solid;
border-color: black;
border-image: initial;
border: 1px solid black;

padding: 1rem 2rem;
`;
31 changes: 27 additions & 4 deletions components/todo-item.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,34 @@
import React from "react";
import styled from "styled-components";

export default function TodoItem() {
return <Wrapper>Todo</Wrapper>;
function TodoItem({ id, content, dueDate, completeTodo }) {
return <Wrapper>
<p style={{"fontSize":"1.5rem","display":"flex","flexDirection":"column","padding":"0px","margin":"0px"}}>{content}</p>
<p style={{"fontSize":"1.5rem","display":"flex","flexDirection":"column","padding":"0px","margin":"0px"}}>{dueDate}
<button style={{"color":"white","backgroundColor":"rgb(97, 97, 97)","fontSize":"1.5rem","outline":"none","borderWidth":"initial","borderStyle":"none","borderColor":"initial","borderImage":"initial","padding":"0.5rem 1rem","borderRadius":"0.3rem"}} onClick={(() => { completeTodo(id) })}>
완료
</button>
</p>
</Wrapper>;
}

const Wrapper = styled.div`
font-size: 18px;
border: solid 1px;
width: 100%;
display: flex;
flex-direction: row;
-webkit-box-pack: justify;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 3rem;
padding: 1rem 2rem;
border-width: 1px;
border-style: solid;
border-color: black;
border-image: initial;
`;

const areEqual = (prevProps, nextProps) => {
return prevProps.id === nextProps.id;
}

export default React.memo(TodoItem, areEqual);
Comment on lines +30 to +34

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

잘 적용해주셨네요!!! 좋습니다 ㅎ 👍

20 changes: 10 additions & 10 deletions components/todo-list.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@ import styled from "styled-components";

import TodoItem from "./todo-item";

export default function TodoList() {
return (
<Wrapper>
Todo list가 들어가는 자리입니다!
<TodoItem />
</Wrapper>
);
export default function TodoList({ todos, completeTodo }) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

TodoList에도 React.memo를 적용해보세요~

return (
<Wrapper>
{todos.sort((todo1, todo2) => {
return todo1.dueDate < todo2.dueDate ? -1 : todo1.dueDate > todo2.dueDate ? 1 : 0;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

sort의 compare 함수는 양수, 0, 음수여부만 판단하기 때문에

Suggested change
return todo1.dueDate < todo2.dueDate ? -1 : todo1.dueDate > todo2.dueDate ? 1 : 0;
return todo1.dueDate - todo2.dueDate;

라고만 해주셔도 됩니다 ㅎ

}).map((todo) => (todo.isComplete ? null : <TodoItem key={todo.id} {...todo} completeTodo={completeTodo} />))}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

map함수에서 3항연산자를 사용해 선택적으로 return 하는 것 보다 filter함수를 쓰는게 더 좋을 것 같아요!

</Wrapper>
);
}

const Wrapper = styled.div`
border: solid 1px;
font-size: 18px;
flex: 1;
font-size: 18px;
flex: 1 1 0%;
`;
1 change: 1 addition & 0 deletions pages/_app.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class PickkApp extends App {
font-size: 0.1rem;
overflow-x: hidden;
width: 100%;
color: white;
}
::-webkit-scrollbar {
display: none;
Expand Down
68 changes: 58 additions & 10 deletions pages/index.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,78 @@
import React from "react";
import React, { useState } from "react";

import TodoInput from "../components/todo-input";
import TodoList from "../components/todo-list";

import styled from "styled-components";

export default function Home() {
const [todos, setTodos] = useState([
])

const [counter, setCounter] = useState(1) // todo 샘플 지울때 0으로 바꾸기.

// todo 추가하기
const addTodo = ({ content, dueDate }) => {
// check whether every input is filled
if ((content === undefined) || (dueDate === undefined)) {
alert('모든 항목을 입력해주세요!');
return;
}

// check whether dueDate is valid
const dateRegExp = /^\d{8}$/;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

정규표현식을 사용해주신 점이 정말 멋있는 것 같아요

if (!dateRegExp.exec(dueDate)) {
alert('날짜를 올바른 형식으로 입력해주세요!');
return;
}

// add todo to todos
// increment counter
setCounter(counter + 1);
setTodos([
...todos,
{ id: counter, content, dueDate, isComplete: false }

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

isComplete 사용하신 것 참신하네요 👍

])

alert('입력 완료!')
}

// todo 완료하기
const completeTodo = (id) => {
setTodos(
todos.map((todo) => todo.id === id ? { ...todo, isComplete: true } : todo)
)
}

return (
<Wrapper>
<Title>리액트-투두</Title>
<Contents>
<TodoInput />
<TodoList />
<TodoInput addTodo={addTodo} />
<div style={{flex:0.3}}></div>
<TodoList completeTodo={completeTodo} todos={todos} />
</Contents>
<div style={{position:'fixed', right:0, top:0, padding: '1px', fontSize:'9px', backgroundColor:'grey'}}>CEOS 11기 정시원</div>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

style을 inline으로 다는 것은 별로 좋은 습관은 아니랍니다 ㅎㅎ

</Wrapper>
);
}

const Wrapper = styled.div`
height: 100vh;
min-height: 100vh;
background-color: rgb(155, 197, 195);
padding: 4rem 5rem;
`;

const Contents = styled.div`
border: solid 1px black;
display: flex;
flex-direction: row;
justify-content: space-between;
padding: 10px 20px;
margin: 20px 10px;
display: flex;
flex-direction: row;
-webkit-box-pack: justify;
justify-content: space-between;
`;

const Title = styled.p`
font-size: 3rem;
font-weight: 600;
padding: 0px;
margin: 0px 0px 3rem;
`