Skip to content

Commit

Permalink
memo.ts가 제대로 셋팅되지 않았던 버그 수정
Browse files Browse the repository at this point in the history
  • Loading branch information
BongjoonKim committed Dec 31, 2024
1 parent 354fb53 commit 00a56d8
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 60 deletions.
54 changes: 11 additions & 43 deletions src/@lib/equalities/deepEquals.ts
Original file line number Diff line number Diff line change
@@ -1,69 +1,37 @@
// export function deepEquals<T>(objA: T, objB: T): boolean {
// if (typeof objA === "object" && typeof objB === "object") {
// if (objA == null && objB == null) {
// return true;
// }
// if (Object.keys(objA).length === Object.keys(objB).length) {
// for (const key of Object.keys(objA)) {
// if (typeof objA[key] === "object" && typeof objB[key] === "object") {
// return deepEquals(objA[key], objB[key]);
// }
// if (objA[key] !== objB[key]) {
// return false;
// }
// }
// return true;
// } else {
// return false;
// }
// } else {
// return objA === objB;
// }
// }

// 깊은 비교
export function deepEquals<T>(objA: T, objB: T): boolean {
// 기본 타입이거나 null/undefined인 경우
// 원시 타입이 같은 경우 확실한 true이다.
if (objA === objB) {
return true;
}

// null/undefined 체크
if (objA == null || objB == null) {
return false;
}

// 배열 체크
if (Array.isArray(objA) && Array.isArray(objB)) {
if (objA.length !== objB.length) {
return false;
}
for (let i = 0; i < objA.length; i++) {
if (!deepEquals(objA[i], objB[i])) {
return false;
}
}
return true;
// 하나라도 null이 있을 경우
if (objA === null || objB === null) {
return objA === objB;
}

// 객체 체크
// 타입이 객체인 경우(배열 포함)
if (typeof objA === "object" && typeof objB === "object") {
const keysA = Object.keys(objA);
const keysB = Object.keys(objB);

// 키 길이가 같은 경우 return false;
if (keysA.length !== keysB.length) {
return false;
}

for (const key of keysA) {
// keysB에 keysA에 있는 키가 없는 경우
if (!keysB.includes(key)) {
return false;
}
// 항상 objA[key], objB[key]를 재귀적으로 deepEquals를 해주는게 포인트
if (!deepEquals(objA[key], objB[key])) {
return false;
}
}
// key와 value가 모두 같다면 return true
return true;
}

// 어떠한 경우도 아니면 false
return false;
}
13 changes: 9 additions & 4 deletions src/@lib/equalities/shallowEquals.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,30 @@
// 얕은 비교
export function shallowEquals<T>(objA: T, objB: T): boolean {

// 두 값이 정확히 같은지 확인(참조가 같은 경우)
if (objA === objB) {
return true;
}
// 하나라고 null이면 false이다. 둘 다 null인 경우는 위의 if문에서 처리됨
if (objA === null || objB === null) {
return objA === objB;
return false;
}

// 둘 다 객체인 경우(배열 포함)
if (typeof objA === "object" && typeof objB === "object") {
if (Object.keys(objA).length !== Object.keys(objB).length) {
const objAKeys = Object.keys(objA);
const objBKeys = Object.keys(objB);
if (objAKeys.length !== objBKeys.length) {
return false;
} else {
for (const key of Object.keys(objA)) {
for (const key of objAKeys) {
if (objA[key] !== objB[key]) {
return false;
}
}
return true;
}
// 모두 아닌 경우
} else {
return objA === objB;
}
Expand Down
1 change: 1 addition & 0 deletions src/@lib/hocs/deepMemo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { deepEquals } from "../equalities";
import { ComponentType } from "react";
import { memo } from "./memo.ts";

// 깊은 메모
export function deepMemo<P extends object>(Component: ComponentType<P>) {
return memo(Component, deepEquals);
}
22 changes: 11 additions & 11 deletions src/@lib/hocs/memo.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import { shallowEquals } from "../equalities";
import { ComponentType } from "react";
import {ComponentType, createElement, ReactNode, useEffect} from "react";
import {useRef} from "../hooks";


export function memo<P extends object>(
Component: ComponentType<P>,
_equals = shallowEquals,
) {
let oldProps = null;
let prevResult = null;
return (props) => {
if (!oldProps || !_equals(oldProps, props)) {
prevResult = Component(props);
}
// 렌더링이 되어도 기존 데이터(prev)를 가지고 있어야 하기 때문에 ref 사용
const prevPropsRef = useRef<P | null>(null);
const prevResultRef = useRef<ReactNode | null>(null);

// 현재 props를 이전 props로 저장
oldProps = props;

// 메모이제이션된 결과 반환
return prevResult;
if (!prevPropsRef.current || !_equals(prevPropsRef.current, props)) {
prevResultRef.current = createElement(Component, props);
}
prevPropsRef.current = props;
return prevResultRef.current;
}
}
4 changes: 2 additions & 2 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, {useState, createContext, useContext, useEffect} from "react";
import { generateItems, renderLog } from "./utils";
import { useCallback, useMemo } from "./@lib";
import {memo} from "react";
import {memo, useCallback, useMemo } from "./@lib";
// import {memo} from "react";
import {deepEquals} from "./@lib";

// 타입 정의
Expand Down

0 comments on commit 00a56d8

Please sign in to comment.