Skip to content

Commit

Permalink
feat: render 및 state에 deepEqual 체크 로직 추가
Browse files Browse the repository at this point in the history
  • Loading branch information
dosilv committed Dec 26, 2024
1 parent ca503f6 commit 98ab635
Show file tree
Hide file tree
Showing 8 changed files with 55 additions and 27 deletions.
12 changes: 10 additions & 2 deletions src/components/posts/Post.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,25 @@
import { createVNode } from "../../lib/index.ts";
import { globalStore } from "../../stores/globalStore.ts";
import { PostData } from "../../stores/type.ts";

import { toTimeFormat } from "../../utils/index.ts";

interface PostProps {
id: number;
author: string;
time: number;
content: string;
likeUsers: string[];
activationLike: boolean;
}

export const Post = ({
id,
author,
time,
content,
likeUsers,
activationLike = false,
}) => {
}: PostProps) => {
const { getState, setState } = globalStore;
const { currentUser, posts } = getState();

Expand Down
8 changes: 7 additions & 1 deletion src/lib/createStore.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { deepEqual } from "../utils/deepEqual.ts";
import { createObserver } from "./createObserver.ts";

type State = { [key: string]: any };
Expand All @@ -11,7 +12,12 @@ export const createStore = <T extends State>(
let state: T = { ...initialState };

const setState = (newState: Partial<T>) => {
state = { ...state, ...newState };
const stateToSet = { ...state, ...newState };

// state가 동일한 경우 업데이트 방지
if (deepEqual(stateToSet, state)) return;

state = stateToSet;
notify();
};

Expand Down
8 changes: 4 additions & 4 deletions src/lib/renderElement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { createElement } from "./createElement";
import { normalizeVNode } from "./normalizeVNode";
import { updateElement } from "./updateElement";
import { VNode } from "./type";
import getNodeStore from "../stores/nodeStore";
import { nodeStore } from "../stores";

export function renderElement(vNode: VNode, container: HTMLElement | null) {
if (!container) return;
Expand All @@ -13,12 +13,12 @@ export function renderElement(vNode: VNode, container: HTMLElement | null) {
if (!prevEl) {
container.appendChild(createElement(normalizeVNode(vNode)));
setupEventListeners(container);
getNodeStore.set(normalizeVNode(vNode));
nodeStore.set(normalizeVNode(vNode));
return;
}

updateElement(container, normalizeVNode(vNode), getNodeStore.get());
getNodeStore.set(normalizeVNode(vNode));
updateElement(container, normalizeVNode(vNode), nodeStore.get());
nodeStore.set(normalizeVNode(vNode));
// container.replaceChild(createElement(normalizeVNode(vNode)), prevEl);
// setupEventListeners(container);
// 최초 렌더링시에는 createElement로 DOM을 생성하고
Expand Down
8 changes: 0 additions & 8 deletions src/lib/typeChecker.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,7 @@
import { VNode } from "./type";

export const isBooleanTrue = (value: any) =>
typeof value === "boolean" && value;

export const isNumberZero = (value: any) => value === 0;

export const stringifyWhen = (value: any) =>
typeof value === "string" || typeof value === "number";

export const returnEmptyStringWhen = (value: any) =>
!value || isBooleanTrue(value);

export const isStringOrNum = (value: any): value is string | number =>
typeof value === "string" || typeof value === "number";
12 changes: 6 additions & 6 deletions src/lib/updateElement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { addEvent, removeEvent } from "./eventManager.ts";
import { createElement } from "./createElement.ts";
import { VNode, VNodeProps } from "./type.ts";
import { getAttributeName, getEventType, isEvent } from "./helper.ts";
import { deepEqual } from "../utils/deepEqual.ts";

function updateAttributes(
$el: HTMLElement,
Expand Down Expand Up @@ -62,10 +63,8 @@ export function updateElement(
}
}

const $newEl = createElement(newNode);

if (!oldNode && newNode) {
return parentElement.appendChild($newEl);
return parentElement.appendChild(createElement(newNode));
}

if (!newNode || !oldNode) return;
Expand All @@ -74,16 +73,17 @@ export function updateElement(
const { type: newType, props: newProps, children: newChildren } = newNode;

if (newType !== oldType) {
return parentElement.replaceChild($newEl, $oldEl);
return parentElement.replaceChild(createElement(newNode), $oldEl);
}

if (!newType && !oldType && newNode !== oldNode) {
return parentElement.replaceChild($newEl, $oldEl);
return parentElement.replaceChild(createElement(newNode), $oldEl);
}

if (!$oldEl) return;

if (newProps !== oldProps) {
// 속성값이 동일한 경우 update 방지
if (!deepEqual(newProps, oldProps)) {
updateAttributes($oldEl, newProps, oldProps);
}

Expand Down
8 changes: 2 additions & 6 deletions src/stores/nodeStore.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { VNode } from "../lib";

const nodeStore = () => {
export const nodeStore = (() => {
let currVNode: VNode | null = null;

return {
Expand All @@ -9,8 +9,4 @@ const nodeStore = () => {
currVNode = vNode;
},
};
};

const getNodeStore = nodeStore();

export default getNodeStore;
})();
25 changes: 25 additions & 0 deletions src/utils/deepEqual.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
export const deepEqual = (obj1: any, obj2: any) => {
if (obj1 === obj2) return true;

if (
typeof obj1 !== "object" ||
obj1 === null ||
typeof obj2 !== "object" ||
obj2 === null
) {
return false;
}

const keys1 = Object.keys(obj1);
const keys2 = Object.keys(obj2);

if (keys1.length !== keys2.length) return false;

for (const key of keys1) {
if (!keys2.includes(key) || !deepEqual(obj1[key], obj2[key])) {
return false;
}
}

return true;
};
1 change: 1 addition & 0 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from "./eventUtils";
export * from "./timeUtils";
export * from "./deepEqual";

0 comments on commit 98ab635

Please sign in to comment.