Skip to content

Commit

Permalink
feat: equalities / memo / useCallback 등등 기본 구현 추가 (기본과제)
Browse files Browse the repository at this point in the history
  • Loading branch information
divopsor committed Dec 28, 2024
1 parent 613cb3f commit 8122211
Show file tree
Hide file tree
Showing 11 changed files with 2,658 additions and 26 deletions.
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"devDependencies": {
"@eslint/js": "^9.9.0",
"@playwright/test": "^1.49.1",
"@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.5.0",
"@testing-library/react": "^16.0.1",
"@testing-library/user-event": "^14.5.2",
Expand All @@ -43,10 +44,10 @@
"@vitejs/plugin-react-swc": "^3.5.0",
"@vitest/coverage-v8": "^2.1.2",
"eslint": "^9.9.0",
"eslint-plugin-react-hooks": "^5.1.0-rc.0",
"eslint-plugin-react-refresh": "^0.4.9",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-react-hooks": "^5.1.0-rc.0",
"eslint-plugin-react-refresh": "^0.4.9",
"globals": "^15.9.0",
"husky": "^9.1.7",
"jsdom": "^25.0.1",
Expand Down
43 changes: 42 additions & 1 deletion src/@lib/equalities/deepEquals.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,44 @@
export function deepEquals<T>(objA: T, objB: T): boolean {
return objA === objB;
if (typeof objA !== typeof objB) {
return false;
}

if (objA == null && objB == null) {
return objA === objB;
}

if (typeof objA !== "object" && typeof objB !== "object") {
return objA === objB;
}

if (Array.isArray(objA) !== Array.isArray(objB)) {
return false;
}

if (Array.isArray(objA) && Array.isArray(objB)) {
if (objA.length !== objB.length) {
return false;
}

return objA.every((value, index) => deepEquals(value, objB[index]));
}

const keysA = Object.keys(objA as object);
const keysB = Object.keys(objB as object);

if (keysA.length !== keysB.length) {
return false;
}

if (keysA.some((key) => !keysB.includes(key))) {
return false;
}

for (const key in objA) {
if (!deepEquals(objA[key], objB[key])) {
return false;
}
}

return true;
}
32 changes: 31 additions & 1 deletion src/@lib/equalities/shallowEquals.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,33 @@
export function shallowEquals<T>(objA: T, objB: T): boolean {
return objA === objB;
if (objA === objB) {
return true;
}

if (
typeof objA !== "object" ||
objA == null ||
typeof objB !== "object" ||
objB == null
) {
return false;
}

const keysA = Object.keys(objA);
const keysB = Object.keys(objB);

if (keysA.length !== keysB.length) {
return false;
}

if (keysA.some((key) => !keysB.includes(key))) {
return false;
}

for (const key in objA) {
if (objA[key] !== objB[key]) {
return false;
}
}

return true;
}
6 changes: 3 additions & 3 deletions src/@lib/hocs/deepMemo.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { deepEquals } from "../equalities";
import { ComponentType } from "react";
import { memo } from "./memo.ts";
import { memo } from "./memo.tsx";

export function deepMemo<P extends object>(Component: ComponentType<P>) {
return memo(Component, deepEquals);
export function deepMemo<P extends object, R>(Component: ComponentType<P>) {
return memo<P, R>(Component, deepEquals);
}
10 changes: 0 additions & 10 deletions src/@lib/hocs/memo.ts

This file was deleted.

19 changes: 19 additions & 0 deletions src/@lib/hocs/memo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { shallowEquals } from "../equalities";
import { ComponentType } from "react";

export function memo<P extends object, R>(
Component: ComponentType<P>,
_equals = shallowEquals,
): (props: P) => R {
const prevProps = { current: { value: {} } as { value: P } };
let memoizedResult: R;

return (props: P) => {
if (!_equals(props, prevProps.current.value)) {
prevProps.current.value = props;
memoizedResult = (<Component {...props} />) as R;
}

return memoizedResult;
};
}
6 changes: 3 additions & 3 deletions src/@lib/hooks/useCallback.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
/* eslint-disable @typescript-eslint/no-unused-vars,@typescript-eslint/no-unsafe-function-type */
/* eslint-disable @typescript-eslint/no-unsafe-function-type */
import { DependencyList } from "react";
import { useMemo } from "./useMemo";

export function useCallback<T extends Function>(
factory: T,
_deps: DependencyList,
) {
// 직접 작성한 useMemo를 통해서 만들어보세요.
return factory as T;
return useMemo(() => factory, _deps);
}
1 change: 0 additions & 1 deletion src/@lib/hooks/useDeepMemo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,5 @@ import { useMemo } from "./useMemo";
import { deepEquals } from "../equalities";

export function useDeepMemo<T>(factory: () => T, deps: DependencyList): T {
// 직접 작성한 useMemo를 참고해서 만들어보세요.
return useMemo(factory, deps, deepEquals);
}
16 changes: 13 additions & 3 deletions src/@lib/hooks/useMemo.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import { DependencyList } from "react";
import { shallowEquals } from "../equalities";
import { useRef } from "./useRef";

export function useMemo<T>(
factory: () => T,
_deps: DependencyList,
_equals = shallowEquals,
): T {
// 직접 작성한 useRef를 통해서 만들어보세요.
return factory();
const ref = useRef<{ deps: DependencyList; value: T } | null>(null);

if (ref.current == null) {
ref.current = { deps: _deps, value: factory() };
return ref.current.value;
}

if (!_equals(_deps, ref.current.deps)) {
ref.current = { deps: _deps, value: factory() };
}

return ref.current.value;
}
7 changes: 5 additions & 2 deletions src/@lib/hooks/useRef.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { useState } from "react";

export function useRef<T>(initialValue: T): { current: T } {
// React의 useState를 이용해서 만들어보세요.
return { current: initialValue };
const [value] = useState<{ current: T }>({ current: initialValue });

return value;
}
Loading

0 comments on commit 8122211

Please sign in to comment.