-
Notifications
You must be signed in to change notification settings - Fork 62
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
[2팀 김경민] [Chapter 1-3] React, Beyond the Basics #43
base: main
Are you sure you want to change the base?
Conversation
Question. hasOwn 메서드에 에러가 발생합니다 어떻게 처리해야 좋을까요?
Q. Context 파일을 만들 때 깔끔한 순서가 있을까?
도원님, 창엽님 감사드립니다
ItemContext을 지정했을 때 리렌더링 되는 영역에 대한 Context 정의할 이유가 부족합니다. 따라서 기존의 context를 제거합니다
// 3. provider | ||
export const UserContextProvider = ({ | ||
children, | ||
}: { | ||
children: React.ReactNode; | ||
}) => { |
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.
children을 props로 받아오는 경우 PropsWithChildren를 사용하면 조금 더 직관적이고 쉽게 타입 정의가 가능합니다 !
children외의 다른 props가 있는 경우 이렇게도 사용 해볼 수 있어요 ㅎㅎ
type ComponentProps = {
title: string;
};
const Component = ({ title, children }: PropsWithChildren<ComponentProps>) => {
return (
<div>
<h1>{title}</h1>
<div>{children}</div>
</div>
);
};
const ThemeContext = createContext<ThemeContextType | null>(null); | ||
|
||
// 3. provider | ||
export const ThemeContextProvider = ({ children }: PropsWithChildren) => { |
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.
엇 여긴 PropsWithChildren을 사용하셨네요
통일화 해주면 좋을 것 같습니다 ! 👍
src/@lib/equalities/deepEquals.ts
Outdated
if ( | ||
typeof objA !== "object" || | ||
objA === null || | ||
typeof objB !== "object" || | ||
objB === null | ||
) { | ||
return false; | ||
} | ||
|
||
// 3. 배열인 경우 처리 | ||
if (Array.isArray(objA) && Array.isArray(objB)) { | ||
if (!Array.isArray(objB) || objA.length !== objB.length) { | ||
return false; | ||
} | ||
|
||
for (let i = 0; i < objA.length; i++) { | ||
if (!deepEquals(objA[i], objB[i])) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
|
||
// 4. 객체의 키 개수가 다른 경우 처리 | ||
const keysA = Object.keys(objA as object); | ||
const keysB = Object.keys(objB as object); | ||
if (keysA.length !== keysB.length) { | ||
return false; | ||
} |
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.
shallowEqual이랑 중복되는 로직들이 있어서 유틸 함수로 분리 할 수도 있을 것 같습니다 :)
src/@lib/hooks/useCallback.ts
Outdated
export function useCallback<T extends Function>( | ||
factory: T, | ||
_deps: DependencyList, | ||
) { | ||
// 직접 작성한 useMemo를 통해서 만들어보세요. | ||
return factory as T; | ||
callback: T, | ||
deps: DependencyList, | ||
equals = shallowEquals | ||
): T { | ||
// useMemo를 사용하여 의존성이 변경될 때만 새로운 함수를 생성 | ||
return useMemo(() => callback, deps, equals); | ||
} |
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.
useMemo를 사용할 때 equals를 따로 전달하신 이유가 있을까요?!
저는 useMemo 내부에서 equals가 지역변수로 취급되어 지정이 되어있고 실제로 리액트의 useCallback는 비교 방식 (얕은, 깊은)을 지정해주지 않기도 해서 따로 equals를 넘겨주지 않았거든요 !
경민님의 의견이 궁금합니다 😊
경민님 이번 과제 너무 고생 많으셨습니다! 항상 경민님을 보며 배울점이 많은 것 같습니다 ㅎㅎ 새해 복 많이 받으세요 ! |
배럴파일: 하나의 파일에 모든 경로를 모으는 방식 장점: import 경로문을 관리해서 코드를 보다 깔끔하게 작성 가능
과제 체크포인트
기본과제
심화 과제
과제 셀프회고
기술적 성장
기존에 알고는 있었지만, 자세히 학습하지 않았던 개념들에 대해서 생각해볼 수 있는 시간이었습니다. 성능 개선을 위해 리렌더링에 대해 잘 알아야 함을 인식하고 있었지만 어떻게 접근해야 할지, 어떻게 학습하는게 모호했었는데 부족한 개념을 채워볼 수 있었던 주간이었습니다.
코드 품질
학습 효과 분석
기본 과제에서는 생각하지 않고 넘겨왔던 지식 부채를 해소하는 시간을 가진 것 같습니다. 공식문서가 생각 이상으로 깔끔하게 잘 정리되어있다는 점을 깨닫고 눈에 익혀둘 필요가 있다 인식하게 되었습니다
심화 과제에서 실전에 적용할만한 부분들을 많이 얻어가는 것 같습니다. 1주차 과제 때만 해도 덩그러니 주어진 자바스크립트 코드만으로 어떤 코드를 작성하고, 정리해야 하는지 너무 막막했던 기억이 납니다. 프론트엔드를 제대로 배워본 적이 없다보니 코드 분할, 클린 코드 형태에 개념이 많이 부족했습니다. 다만 이번주차는 기본 과제에 힘을 뺄 수 있어서 오히려 심화과제를 통해 실제 업무에 적용해볼만한 점들을 고민해볼 수 있었던것이 큰 경험이 되었습니다.
AI의 사용은 항상 경계해야겠다는 생각을 합니다. 테스트 코드를 동작하는 코드를 보기 전까지 다소 수용적인 태도로 AI를 신뢰했던 것이 여전히 과제를 하면서 오점을 남겼던 것 같습니다. 코드 작성 대신 추천기능을, 추천 기능 대신에 개념의 정확한 이해가 있어야 한다고 생각하면서도, 동작하지 않는 코드를 보면서 개념을 제대로 인식하고 있는 것인지에 대해 불안함을 갖고 있다보니, 학습 프로세스가 정립되지 못하는 것 같은 아쉬움을 가지고 있습니다.
과제 피드백
팀원들을 통해 고민을 해결하는 순간이 큰 기쁨으로 다가왔습니다. 가려운 부분을 손쉽게 긁을 수 있었서 과제를 마쳤다는 해소감도 있었지만,
사수 없이 고민하면서 겪는 외로움이나 불안함 같은 심적인 부분들에 의지가 되어준 경험이었습니다.
테스트코드나 기타 라이브러리 등에 대해 아직 모르는 부분이 많다보니 과제 진행중 막힐 때마다 힘든 고비들이 있습니다. 이번 과제의 경우 husky에 익숙하지 않은데 커밋이 동작되지 않는 문제를 해결하기 위해 코드를 수정해야 했으며, package.json 또한 eslint 부분을 지워야 했습니다. 명확한 개념을 갖지 못하는 라이브러리에 대해 코드 수정을 하거나 마주해야 하는 부담이 큰것 같습니다. husky, test code를 파악하는 과정, 기타 package에 대한 설명이 있었으면 좋겠습니다.
리뷰 받고 싶은 내용
항해과정에 도전하면서 상태관리 라이브러리에 대한 고민이 많았습니다. 혼자 개발과 학습을 동시에 진행하며 개념이 다져지기 전부터 뼈대를 올리다보니 매 주 과거의 코드를 개선해야겠다는 생각이 많습니다.
팀원분들과 대화하며 ContextAPI을 정확하기 적용하기 위해선 필요한 부분에 Provider를 씌워야 하는 불편함이 있다는 점이 있고, 때문에 현업에서 Jotai, Zustand와 같은 상태관리 라이브러리가 ContextAPI 보다 보편적으로 다뤄지는 것으로 이해했습니다. 항해에서 배운 내용을 업무 코드 개선에 적용하려고 하는데, ContextAPI를 그대로 적용하는 것이 아닌 Jotai, Zustand, Recoil을 적용하는 것이 좋을지 아닐지에 대한 코치님의 의견이 필요합니다.
상태관리에 대한 구조를 어떻게 잡아가는 것이 좋은 효율을 가질지 고민입니다. 1주차 2주차를 통해 다른 분들의 코드를 보면 store 폴더 아래 상태 자체를 파일로 관리하는 코드형식을 보고 배웠던적이 있습니다. 다만 이것이 상태관리 라이브러리를 사용하지 않는다는 제약 하에서 좋은 코드 형태인 것인지, 상태관리 라이브러리를 적극 사용할 때에도 store 폴더로 분리해서 사용하는 것이 좋을지에 대한 가름이 필요합니다.
ItemList 컴포넌트의 addItems, filteredItems, totalPrice, averagePrice를 useItem, usePrice로 분리해 볼 수 있지 않을까 싶었는데, 개선에. hook 분리 능력이 부족한 것 같아 피드백 요청드립니다. 아래 세개의 선택지 중 어떤 방식이 더 좋을지 고민입니다.
(개선 시도해본 코드를 보실 수 있도록 추가 커밋 올려두겠습니다)