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

[3주차] 정대헌 미션 제출합니다. #21

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
46 changes: 34 additions & 12 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,16 @@
"@testing-library/jest-dom": "^5.16.2",
"@testing-library/react": "^12.1.4",
"@testing-library/user-event": "^13.5.0",
"@types/jest": "^27.4.1",
"@types/node": "^17.0.23",
"@types/react": "^17.0.43",
"@types/react-dom": "^17.0.14",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-icons": "^4.3.1",
"react-scripts": "5.0.0",
"styled-components": "^5.3.3",
"typescript": "^4.6.3",
"web-vitals": "^2.1.4"
},
"scripts": {
Expand All @@ -36,5 +41,8 @@
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"@types/styled-components": "^5.1.24"
}
}
34 changes: 0 additions & 34 deletions src/App.js

This file was deleted.

24 changes: 24 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React from "react";

import { GlobalProvider } from "./context/GlobalContext";
import InputContainer from "./containers/InputContainer";
import ListItemContainer from "./containers/ListItemContainer";
import GlobalStyle from "./GlobalStyles";
import { ItemType } from "./Objects";

function App() {
return (
<GlobalProvider>
<GlobalStyle />
<div className="background">
<div className="container">
<InputContainer />
<ListItemContainer title={"해야할 일"} listType={ItemType.Todo} />
<ListItemContainer title={"완료한 일"} listType={ItemType.Done} />
</div>
</div>
Comment on lines +13 to +19

Choose a reason for hiding this comment

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

구조가 깔끔해서 보기 좋네요

Copy link
Author

Choose a reason for hiding this comment

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

감사합니다 :)

</GlobalProvider>
);
}

export default App;
7 changes: 1 addition & 6 deletions src/GlobalStyles.js → src/GlobalStyles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,7 @@ export default createGlobalStyle`
display: grid;
place-items: center;
background-color: #fa8bff;
background-image: linear-gradient(
45deg,
#fa8bff 0%,
#2bd2ff 52%,
#2bff88 90%
);
background-image: linear-gradient(120deg, #fccb90 0%, #d57eeb 100%);
font-family: var(--ff-main);
color: white;
}
Expand Down
13 changes: 13 additions & 0 deletions src/Objects.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export type Item = {
id: string,
type?: ItemType,
content?: string,
}

export enum ItemType {Todo, Done}

export type Action = {type: ActionType, payload: any}
Copy link

Choose a reason for hiding this comment

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

액션은 정확하게 작성해주시는게 좋습니다. 각 action별로 payload의 타입이 전부 다를텐데, 이걸 컴파일 타임에 검사를 안해주면 런타임에 잘못된 코드가 들어왔을 때 대비가 안될 수 있죠.

Copy link
Author

Choose a reason for hiding this comment

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

맞습니다, 제가 any로 두고 고치질 않았군요. 수정하겠습니다 :)

Suggested change
export type Action = {type: ActionType, payload: any}
export type Action = {type: ActionType, payload: Item}


export enum ActionType {DELETE, ADD, MODIFY }

export type State = Item[]
33 changes: 26 additions & 7 deletions src/components/ListItem.js → src/components/ListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ import React, { useContext } from "react";
import { FaTrash } from "react-icons/fa";
import styled from "styled-components";

import { GlobalContext } from "../context/GlobalState";
import { DispatchContext} from "../context/GlobalContext";
import { Item, ActionType, ItemType } from "../Objects";

const Item = styled.div`
const ItemDiv = styled.div`
display: flex;
width: "100%";
justify-content: space-between;
Expand Down Expand Up @@ -70,11 +71,29 @@ const DeleteIcon = styled.p`
color: gray;
`;

const ListItem = ({ item }) => {
const { deleteItem, moveItem } = useContext(GlobalContext);
const ListItem = ({ item }: {item: Item}) => {
const dispatch = useContext(DispatchContext);
Comment on lines +74 to +75
Copy link

Choose a reason for hiding this comment

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

const ListItem = ( {item} : Item)
이렇게는 작성하면 혹시 오류가 날까요?!,,

Copy link
Author

Choose a reason for hiding this comment

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

말씀하신 대로 수정해보았는데, prop를 2개를 받고 있어서 오류가 나는 것 같아요!
map 사용 시 필요한 key를 prop으로 받고 있습니다~


const moveItem = (uid: string) => {
dispatch({
type: ActionType.MODIFY,
payload: {
id: uid,
},
});
};

const deleteItem = (uid: string) => {
dispatch({
type: ActionType.DELETE,
payload: {
id: uid,
},
});
};

return (
<Item>
<ItemDiv>
<ItemScrollDiv>
<ItemFinishButton
type="button"
Expand All @@ -84,7 +103,7 @@ const ListItem = ({ item }) => {
>
<ItemTitle>
{/* listType의 done/todo에 따라 del 태그 삽입 */}
{item.type === "done" ? <del>{item.content}</del> : item.content}
{item.type === ItemType.Done ? <del>{item.content}</del> : item.content}
Copy link

Choose a reason for hiding this comment

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

태그로 감싸는것도 새로운 방법이네요. 하지만 실제로는 css로 처리하는게 렌더링 성능에서 더 유리하다고 합니다!

Copy link
Author

Choose a reason for hiding this comment

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

조언 감사합니다~ 저는 오히려 css로 처리하는 방법을 생각하지 못했네요, 참고하겠습니다.

</ItemTitle>
</ItemFinishButton>
</ItemScrollDiv>
Expand All @@ -98,7 +117,7 @@ const ListItem = ({ item }) => {
<FaTrash />
</DeleteIcon>
</ItemDeleteButton>
</Item>
</ItemDiv>
);
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import React, { useState, useContext } from "react";
import styled from "styled-components";

import { GlobalContext } from "../context/GlobalState";
import { DispatchContext } from "../context/GlobalContext";
import { ActionType, ItemType } from "../Objects";

const AppInput = styled.div`
width: 28rem;
Expand Down Expand Up @@ -58,15 +59,22 @@ const SubmitBtn = styled.button`
}
`;

const InputContainer = (props) => {
const InputContainer = () => {
const [text, setText] = useState("");
const { addItem } = useContext(GlobalContext);
const dispatch = useContext(DispatchContext);

const submitHandler = (e) => {
const addItem = (uid:string, itemType: ItemType, itemContent: string) => {
dispatch({
type: ActionType.ADD,
payload: { id: uid, type: itemType, content: itemContent },
});
};

Comment on lines +66 to +72

Choose a reason for hiding this comment

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

리덕스 적용하신 것까지 멋있어요

Copy link
Author

Choose a reason for hiding this comment

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

감사합니다!

const submitHandler = (e:React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
if (text !== "") {
const uid = new Date().getTime().toString();
addItem(uid, "todo", text);
addItem(uid, ItemType.Todo, text);
setText("");
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import React, { useContext } from "react";
import styled from "styled-components";

import ListItem from "../components/ListItem";
import { GlobalContext } from "../context/GlobalState";
import { StateContext } from "../context/GlobalContext";
import { ItemType } from "../Objects";

const ItemSection = styled.section`
display: flex;
Expand All @@ -25,8 +26,8 @@ const SectionTitle = styled.h4`
margin-bottom: 1rem;
`;

const ListItemContainer = ({ title, listType }) => {
const { listItems } = useContext(GlobalContext);
const ListItemContainer = ({ title, listType }:{title: String, listType: ItemType}) => {
const listItems = useContext(StateContext);

return (
<ItemSection>
Expand Down
21 changes: 0 additions & 21 deletions src/context/AppReducer.js

This file was deleted.

22 changes: 22 additions & 0 deletions src/context/AppReducer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import {Item, ItemType, Action, ActionType, State} from "../Objects"

const AppReducer = (state: State, action: Action):State => {
switch (action.type) {
case ActionType.DELETE:
return [...state.filter((item) => item.id !== action.payload.id)];
case ActionType.ADD:
return [...state.concat([action.payload])];
case ActionType.MODIFY:
return [
...state.map((item: Item) =>
item.id === action.payload.id
? { ...item, type: item.type === ItemType.Todo ? ItemType.Done : ItemType.Todo }
: item
),
];
Comment on lines +9 to +16
Copy link

Choose a reason for hiding this comment

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

리듀서는 항상 순수함수로 작성하시는게 좋아요. 같은 iditem이 들어와도 type 여부에 따라 리듀서가 리턴하는 값이 달라지죠? 아직은 애플리케이션의 상태가 작지만, 어플리케이션의 규모가 커지면 이런 부분에서 디버깅이 고통스러워질 수 있습니다

Copy link
Author

Choose a reason for hiding this comment

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

순수함수라는건 외부에 함수를 정의하고 모듈로 불러오는 것을 말하시는 것인가요?

default:
return [...state];
}
};

export default AppReducer;
Loading