useState는 함수 컴포넌트 내부에서 상태를 정의하고, 이 상태를 관리할 수 있게 하는 훅이다.
function useState(initState) {
let state = initState; // state를 정의한다. 함수가 실행될 때마다 initState로 초기화된다.
const setState = (newState) => {
state = newState; // 새로운 state를 할당한다.
render(); // render를 실행한다.
}
return [ state, setState ];
}
따라서 state의 값은 내부가 아닌 외부에서 관리해야 한다.
let state = undefined; // state는 외부에서 관리되어야 한다.
function useState(initState) {
if(state ===undefined){
state = initState; // state에 값이 없는 경우에만 초기화 진행
}
const setState = (newState) => {
state = newState; // 새로운 state를 할당한다.
render(); // render를 실행한다.
}
return [ state, setState ];
}
let states = [];
let currentIndex = 0;
const useState = (initState) => {
const index = currentIndex;
// states의 내부 데이터 초기값 설정
if (states.length === index) {
states.push(initState);
}
// state : 초기값을 담은 변수
const state = states[index];
const setState = (newState) => {
// setState 내부에서는 newState가 변환이 없는 경우 실행 중지
if (states[index] === newState) {
return;
}
// 새로운 값으로 변경되는 경우 newState로 업데이트하고 callback() 실행
states[index] = newState;
callback();
};
currentIndex += 1;
return [state, setState];
};
const resetContext = () => {
currentIndex = 0; // 다시 0부터 접근할 수 있도록 값을 초기화 해야 한다.
};
useMemo는 리액트에서 컴포넌트의 성능을 최적화 하는데 사용되는 훅이다.
useMemo에서 memo는 memoization을 뜻하는데 그대로 해석하면 '메모리에 넣기'라는 의미이며 컴퓨터 프로그램이 동일한 계산을 반복해야 할 때, 이전에 계산한 값을 메모리에 저장함으로써 동일한 계산의 반복 수행을 제거하여 프로그램 실행 속도를 빠르게 하는 기술이다.
쉽게 말해 동일한 값을 변환하는 함수를 반복적으로 호출해야한다면 처음 값을 계산할 때 해당 값을 메모리에 저장해 필요할 때마다 다시 계산하지 않고 메모리에서 꺼내서 재사용하는 것
리액트에서 함수형 컴포넌트는
렌더링 ➡️ 컴포넌트 함수 호출 ➡️ 모든 내부 변수 초기화
순서를 거친다.
useMomo훅을 사용하면
렌더링 ➡️ 컴포넌트 함수 호출 ➡️ memoize 된 함수 재사용
하는 순서를 거친다.
이런 방식으로 처음에 계산된 값을 메모리에 저장해 컴포넌트가 계속 렌더링되어도 함수를 재호출하지 않고 메모리에 저장되어있는 계산된 값을 가져와 재사용할 수 있게 해준다.
useMemo를 Js로 변경하여 구현해본 코드이다.
1. useMemo에 들어온 값은 초기값이 없는 경우, 그리고 초기값과 새로 업데이트된 값이 일치하지 않는 경우에 값은 변경된다.
const isSameValue = (a, b) => {
const max = Math.max(a.length, b.length);
for (let i = 0; i < max; i += 1) {
if (a[i] === b[i].refs[0]) {
return true;
}
return false;
}
};
const useMemo = (fn, refs) => {
const index = currentIndex;
// 최초시작 혹은 디펜던시가 변경된 경우
if (states[index] === undefined || !isSameValue(refs, states)) {
states[index] = { result: fn(), refs };
}
return states[index].result;
};