virtual dom을 하고 diff알고리즘을 적용해서 사용하다 보니 useEffect부분이 문제가 발생했었다.
useEffect로직에서 문제가 일어난것인데 기존의 로직은 dependencies와 일치하면 callback을 바로 실행하도록 설정이 되어있다.
const useEffect = (callback, dependencies) => {
if (reRenderCount === 0) {
deps[depsCursor] = dependencies;
callback();
} else {
const oldDependencies = deps[depsCursor];
let hasChanged = !dependencies.every((dep, i) => {
return Object.is(dep, oldDependencies[i]);
});
if (hasChanged) {
deps[depsCursor] = dependencies;
callback();
}
}
depsCursor += 1;
};
실제 우리가 사용하는 React의 useEffect를 보면 랜더링이 모두 일어난 후에 callback이 실행되는걸 알수 있다 따라서 이 callback을 랜더링이 완료되고 실행되도록 시점을 옮겨주어야 한다.
let hookQueue = [];
// useEffect를 저장하는 배열
const reRender = () => {
reRenderCount += 1;
cursor = 0;
depsCursor = 0;
updateElement(
rootElement.childNodes[0],
rootElement.childNodes[0],
rootComponent()
);
while (hookQueue.length) {
hookQueue.shift().callback();
}
};
const useEffect = (callback, dependencies) => {
if (reRenderCount === 0) {
deps[depsCursor] = dependencies;
hookQueue.push({ callback });
} else {
const oldDependencies = deps[depsCursor];
let hasChanged = !dependencies.every((dep, i) => {
return Object.is(dep, oldDependencies[i]);
});
if (hasChanged) {
deps[depsCursor] = dependencies;
hookQueue.push({ callback });
}
}
depsCursor += 1;
};
hookQueue를 만들어서 jsx의 업데이트까지 끝나고 callback을 실행시키도록 수정하였다.
기존에 jsx에서는 HTMLElement만 적용할 수 있었다 나중에 최종 프로젝트때 무언가를 만드려면 컴포넌트를 쪼개서 사용해야 한다. 이를 구현해보자