[1팀 이의찬] Chapter 1-3. React, Beyond the Basics#36
Open
Legitgoons wants to merge 21 commits intohanghae-plus:mainfrom
Open
[1팀 이의찬] Chapter 1-3. React, Beyond the Basics#36Legitgoons wants to merge 21 commits intohanghae-plus:mainfrom
Legitgoons wants to merge 21 commits intohanghae-plus:mainfrom
Conversation
jinsoul75
reviewed
Jul 25, 2025
Comment on lines
+1
to
+29
| /** | ||
| * 주어진 값이 객체인지 확인하는 함수 | ||
| * @reference https://github.com/toss/es-toolkit/blob/main/src/compat/predicate/isObject.ts | ||
| * @param {unknown} value - 객체인지 확인할 값 | ||
| * @returns {value is Record<string, unknown>} 객체인지 확인 결과 | ||
| */ | ||
| export function isObject(value?: unknown): value is Record<string, unknown> { | ||
| return value !== null && typeof value === "object"; | ||
| } | ||
|
|
||
| /** | ||
| * 두 객체를 비교하는 함수 | ||
| * @param a 비교할 첫 번째 객체 | ||
| * @param b 비교할 두 번째 객체 | ||
| * @returns 두 객체가 같은지 확인 결과 | ||
| */ | ||
| export function compareObject( | ||
| a: Record<string, unknown>, | ||
| b: Record<string, unknown>, | ||
| compareFn: (a: unknown, b: unknown) => boolean = (a, b) => a === b, | ||
| ): boolean { | ||
| // 객체의 키 개수가 다른 경우 처리 | ||
| const keysA = Object.keys(a); | ||
| const keysB = Object.keys(b); | ||
| if (keysA.length !== keysB.length) return false; | ||
|
|
||
| // 모든 키에 대해 비교 수행 | ||
| return keysA.every((key) => compareFn(a[key], b[key])); | ||
| } |
There was a problem hiding this comment.
compareObject 함수명만 봤을 때 상세 동작을 상상하기가 어려운 것 같아요! 참조값을 비교하는지, 키값을 비교하는지 더 명확하게 알 수 있으면 좋을 것 같아요!! compareObject로 분리하는 것 좋네요 반복되는 로직이었는데! 👍🏻
angielxx
reviewed
Jul 26, 2025
| // useSyncExternalStore 에서 활용할 수 있도록 subscribe 함수를 수정합니다. | ||
| const subscribe = (fn: Listener) => { | ||
| listeners.add(fn); | ||
| return () => { |
There was a problem hiding this comment.
subscribe에서 반환해주는 함수 로직이 unsubscribe랑 동일하니까 unsubscribe를 그대로 반환해주면 될 것 같아요!
angielxx
reviewed
Jul 26, 2025
angielxx
reviewed
Jul 26, 2025
| // 직접 작성한 useRef를 통해서 만들어보세요. | ||
| return factory(); | ||
| // 1. 이전 의존성과 결과를 저장할 ref 생성 | ||
| const ref = useRef<{ deps: DependencyList; result: T } | null>(null); |
There was a problem hiding this comment.
주석이 없어도 이 ref값이 잘 이해되도록 구체적인 변수명으로 해주면 더 좋을 것 같아요!
angielxx
reviewed
Jul 26, 2025
| return useSyncExternalStore( | ||
| router.subscribe, | ||
| () => shallowSelector(router), | ||
| () => shallowSelector(router), |
There was a problem hiding this comment.
getServerSnapshot 파라미터는 useRouter 파라미터에 옵션으로 넣어줘도 될 것 같아요
export const useRouter = <T extends RouterInstance<AnyFunction>, S>(
router: T,
selector = defaultSelector<T, S>,
getServerSnapshot?: () => S, // 옵셔널 파라미터
) => {
// useSyncExternalStore를 사용하여 router의 상태를 구독하고 가져오는 훅을 구현합니다.
const shallowSelector = useShallowSelector(selector);
return shallowSelector(router);
return useSyncExternalStore(
router.subscribe,
() => shallowSelector(router),
getServerSnapshot // 변경
// 생략
angielxx
reviewed
Jul 26, 2025
| if (prevState === undefined) return initialValue; | ||
|
|
||
| // 함수형 업데이트인지 확인 | ||
| const nextValue = typeof action === "function" ? (action as (prev: T) => T)(prevState) : action; |
There was a problem hiding this comment.
오 함수형 업데이트도 확인하는 로직이 있네요 저는 생각 못 한 케이스네요 굿!! 👍🏻
angielxx
reviewed
Jul 26, 2025
| export const useStorage = <T>(storage: Storage<T>) => { | ||
| // useSyncExternalStore를 사용해서 storage의 상태를 구독하고 가져오는 훅을 구현해보세요. | ||
| return storage.get(); | ||
| return useSyncExternalStore(storage.subscribe, storage.get, storage.get); |
There was a problem hiding this comment.
storage를 사용하는 훅이니까 세번째 서버 스냅샷 가져오는 함수 파라미터는 안 넣어줘도 되지 않을까요? 대부분 storage는 서버랑 관련이 없는 클라이언트 스토리지일테니까요!
angielxx
reviewed
Jul 26, 2025
| return useSyncExternalStore( | ||
| store.subscribe, | ||
| () => shallowSelector(store.getState()), | ||
| () => shallowSelector(store.getState()), |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
과제 체크포인트
배포 링크
https://legitgoons.github.io/front_6th_chapter1-3
기본과제
equalities
hooks
High Order Components
심화 과제
hooks
context
과제 셀프회고
~~~를 구현해보려고 하는데 가이드를 해줘. 처음부터 정답을 알려주지 말고 내가 충분히 학습하면서 정답에 가까워질 수 있도록 질문을 하면서 정답까지 이끌어줘.라는 방식의 프롬프트를 사용해보라고 조언해주셔서 다음 과제부터는 이렇게 해보려고 합니다.기술적 성장
자랑하고 싶은 코드
커밋 링크
feat: 타입 가드를 사용해 isObject 구현
refactor: equals/util에 helper함수 compareObject 구현
return keysA.every((key) => compareFn(a[key], b[key]));부분에서 로직이 달라 어떻게 해야할지 고민했습니다.deepEquals/shallowEquals를 매개변수로 받아서 이에 따라 적용개선이 필요하다고 생각하는 코드
학습 효과 분석
과제 피드백
학습 갈무리
리액트의 렌더링이 어떻게 이루어지는지 정리해주세요.
메모이제이션에 대한 나의 생각을 적어주세요.
컨텍스트와 상태관리에 대한 나의 생각을 적어주세요.
리뷰 받고 싶은 내용