Skip to content

Conversation

@dalcon10028
Copy link

🎯 요구사항

  1. User 추가하기
  2. User의 투두리스트 불러오기
  3. User 삭제하기
  4. todoItem 추가하기
  5. todoItem 불러오기
  6. todoItem complete하기
  7. todoItem 삭제하기
  8. todoItem contents 내용 수정하기
    🎯🎯 심화 요구사항
  9. 데이터를 불러오기전 로딩바를 이용해, 사용자가 데이터가 불러와지고 있다는 것을 보여줍니다.
  10. fetch api 사용하는 부분을 async await을 사용하여 리팩토링합니다.
  11. github issue에서 라벨을 붙이는 것처럼, 우선순위에 따라서 badge를 추가합니다.
  12. ES6 impot & export를 이용해 자바스크립트 파일을 리팩토링합니다.
    🕵️‍♂️ 제약사항
  13. User의 이름은 최소 2글자 이상이어야 합니다.
  14. TodoItem의 콘텐츠는 최소 2글자 이상이어야 합니다.

Copy link

@HongJungKim-dev HongJungKim-dev left a comment

Choose a reason for hiding this comment

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

전반적으로 코드를 이해하기 쉽게 작성하신것 같습니다~ 고생하셨습니다!


this.todoList.addEventListener('change', ({ target }) => {
if (target.tagName !== 'SELECT') return;
const { id } = target.parentNode.parentNode.parentNode.dataset;

Choose a reason for hiding this comment

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

target.parentNode를 하나의 변수에 넣고 그 변수에서 다시 parentNode를 접근하는식으로 변수명으로 의미를 더 드러내는것은 어떤가요? 제가 이해를 못하는것인지 반복하여 parentNode로 접근하여 헷갈리는것 같습니다!

Copy link
Author

Choose a reason for hiding this comment

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

좀 더 좋은 id 접근 방식을 고려해봐야 될 것 같습니다 조언 감사합니다 !

Copy link

@hyoungnam hyoungnam left a comment

Choose a reason for hiding this comment

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

loading 처리 및 요구사항을 정확히 파악하고 구현하셔서 좋았습니다:)

Comment on lines +26 to +60
changeActiveUser: async (id) => {
try {
const { _id, name, todoList } = await userAPI.fetchUser(id);
this.setState({
...this.state,
activeId: _id,
activeUsername: name,
activeTodolist: todoList,
});
} catch (error) {
throw new Error(error);
}
},
createUser: async (name) => {
try {
const newUser = await userAPI.createUser({ name });
this.setState({
...this.state,
activeId: newUser._id,
activeUsername: newUser.name,
activeTodolist: newUser.todoList,
});
} catch (error) {
throw new Error(error);
}
},
deleteUser: async () => {
try {
await userAPI.deleteUser(this.state.activeId);
this.init();
} catch (error) {
throw new Error(error);
}
},
});

Choose a reason for hiding this comment

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

App이 너무 거대하기에 콜백로직부분들을 외부로 빼서 정리하는것도 좋을꺼 같습니다.

Comment on lines +77 to +78
const main = document.createElement('section');
main.className = 'main';

Choose a reason for hiding this comment

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

main 생성과 append하는 부분이 너무 떨어져 있습니다. 정적으로 변하지 않는 부분을 $target으로 해도 괜찮을꺼 같아요

activeTodolist: todoList,
});
} catch (error) {
throw new Error(error);

Choose a reason for hiding this comment

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

throw를 하면 어디서 잡게되나요?

try {
this.state = nextState;
this.todoList.setState({
isLoading: true,

Choose a reason for hiding this comment

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

저는 isLoading 처리를 안했는데 저도 해야겠습니닿ㅎㅎ

Comment on lines +18 to +30
const options = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
};
return $request(url, options);
},
put: (url, body) => {
const options = {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
};

Choose a reason for hiding this comment

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

반복되는 option들도 재사용 가능하도록 고치면 좋을꺼 같아요

@@ -0,0 +1,31 @@
import { $http } from './index.js';

Choose a reason for hiding this comment

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

http에 $는 어떤 의미인가요?

this.countContainer.addEventListener('click', ({ target }) => {
if (!target.dataset.action) return;
const { action } = target.dataset;
console.log(action);

Choose a reason for hiding this comment

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

사용하지 않는 콘솔 로그는 지워주세요:)

input.placeholder = '할 일을 입력해주세요';
input.autofocus = true;
input.addEventListener('keypress', ({ key, target }) => {
if (key !== 'Enter' || target.value < 2) return;

Choose a reason for hiding this comment

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

조건 처리 깔끔해요!

Comment on lines +63 to +77
if (this.state.isLoading)
this.todoList.innerHTML = `
<li>
<div class="view">
<label class="label">
<div class="animated-background">
<div class="skel-mask-container">
<div class="skel-mask"></div>
</div>
</div>
</label>
</div>
</li>
`;
else

Choose a reason for hiding this comment

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

if else 대신 this.state.isLoading ? ~ : ~ 이렇게 처리해도 좋을꺼 같습니다

try {
const res = await fetch(`${BASE_URL}/${url}`, options);
if (!res.ok) {
throw new Error('서버의 상태가 이상합니다');

Choose a reason for hiding this comment

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

예외 처리가 잘 되어있는 거 같습니다 !

Copy link

@soonysoo soonysoo left a comment

Choose a reason for hiding this comment

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

안녕하세요 연권님~ 😄
지난 주도 미션하시느라 수고많으셨습니다!ㅎㅎ

코드 보면서 많이 배워갑니당~ㅎㅎ
벌써 다음 미션이 무섭지만... 다음 주도 같이 화이팅해용 ㅠㅠ...

userList: [],
activeId: '',
activeUsername: '',
activeTodolist: [],

Choose a reason for hiding this comment

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

active 된 유저에 대해서는 하나로 묶어서 정의하면 더 가독성이 좋지 않을까요~?

Comment on lines +6 to +8
if (!res.ok) {
throw new Error(res.status);
}

Choose a reason for hiding this comment

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

res.ok일 때만 await res.json() 가 아니고 반대로 !res.ok일때 예외처리를 하는게 어떤 면에서 이점이 있나용?
제가 잘 몰라서 묻습니다 ㅠㅠ

Copy link
Author

Choose a reason for hiding this comment

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

fetch()로 부터 반환되는 Promise 객체는 HTTP error 상태를 reject하지 않아서 따로 처리했습니다 !
말씀하신 아래 코드와 동일한 것 같습니다.

if (res.ok) {
  await res.json()
}
throw new Error(res.status);

https://developer.mozilla.org/ko/docs/Web/API/Fetch_API/Using_Fetch

Comment on lines +1 to +3
const ALL = 'all';
const ACTIVE = 'active';
const COMPLETED = 'completed';

Choose a reason for hiding this comment

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

다 따로 만드신 이유가 따로 있으신가요~?
Filter안에 ALL, ACTIVE, COMPLETE 넣어놓으면 더 가독성이 있어보일 것 같습니다 ㅎㅎ

Comment on lines +13 to +14
this.todoList = document.createElement('ul');
this.todoList.className = 'todo-list';

Choose a reason for hiding this comment

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

기존에 HTML에 있는 것 활용하시면 더 좋을 것 같아용 😄

});

this.todoList.addEventListener('keypress', ({ key, target }) => {
if (key !== 'Enter' || target.value < 2) return;

Choose a reason for hiding this comment

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

저는 두 개 나눠서 처리했는데 한번에 처리하니까 깔끔하고 좋네요!
배워갑니당 👍

}

render() {
if (this.state.isLoading)

Choose a reason for hiding this comment

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

loading까지 구현하시고 꼼꼼하십니당 💯

<button class="destroy"></button>
</div>
<input class="edit" value="${contents}" />
</li>

Choose a reason for hiding this comment

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

이 부분을 활용하셔서 각각의 js로 HTML에 id를 불러오거나 classname 등록하는 함수 사용을 줄이시는 것을 추천드립니다! ㅎㅎ

<option value="1">1순위</option>
<option value="2">2순위</option>
</select>`;
}

Choose a reason for hiding this comment

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

if else절보다 if문으로 조건을 명시하여 가독성을 높이는 것도 좋을거 같아요 ㅎㅎ

Copy link
Author

@dalcon10028 dalcon10028 left a comment

Choose a reason for hiding this comment

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

내 코드 리뷰

}
},
onChange: async (id, priority) => {
try {
Copy link
Author

Choose a reason for hiding this comment

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

api부분에 try-catch가 작성됐기 때문에 try-catch를 빼고 api에서 에러 처리를 하거나 여기서 에러에 대한 처리를 해줘야 할 것 같습니다.

return $http.get(`api/users/${userId}/items`);
},

createItem(userId, contents) {
Copy link
Author

Choose a reason for hiding this comment

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

contents에 대한 타입이나 dto가 명시되어 있거나 정의한 형태가 아닐 경우 제한하면 더 좋을 것 같습니다.


this.todoList.addEventListener('click', ({ target }) => {
if (target.className === 'toggle') {
const { id } = target.parentNode.parentNode.dataset;
Copy link
Author

Choose a reason for hiding this comment

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

아래와 동일한 코드를 줄이는 게 좋을 것 같습니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants