TOSS개발자
Effect가 필요하지 않을 수도 있다.
어떤 방식으로든 외부 세계에 영향을 미치는 동작
ex) setInterval, setTimeout , console.log, DOM 엘리먼트 너비, 높이, 위치 측정...
리액트에서 제공하는 부수효과 훅
useEffect(()=>{})
useEffect(()=>{},[])
useEffect(()=>{},[dep1, dep2])
: 메모리 누수 방지와 불필요한 이벤트 리스너 제거 등의 목적으로 사용한다.
useEffect(()=>{
return ()=> {// clean up 함수 (정리함수)
}
},[])
✔️ Cleanup 함수의 실행 타이밍
예시 ) 이벤트 리스너, setTime, setInterval 웹소켓 연결
=> 브라우저가 화면을 그리기 전에 효과를 실행
: DOM이 변경된 직후, 브라우저가 화면을 그리기 전에 동기적으로 실행
⚠️ useEffect는 비동기적으로 실행되지만 useLayoutEffect는 동기적으로 실행되기 때문에
무거운 작업 수행시 UI가 멈출 수 있음..!
사용예시 : DOM크기 측정, 레이아웃 조정
App컴포넌트를 React.strictMode가 감싸고 있다.
React.StrictMode는 React.Fragment와 동일하게 실제로 웹 페이지상으로는 전혀 출력되지 않는다.
React.StrictMode란 개발자들에게 해당 코드가 잠재적인 문제를 가지고 있는지 알리기 위해 개발 모드에서 사용되는 기능이다.
페이지를 오고 갈 때마다 이전 상태를 유지한 상태로 리마운트 한다면 여러번 리마운트 될 때마다 화면이 달라지지 않고 같은 화면을 표시할 수 있어야하기 때문에 문제가 생기는 부분이 있는지 확인할 수 있도록 StrictMode를 제공한다.
참고(참고URL)
let currentHook = 0;
let hooks = [];
// 호출 순서
const useState = (initialValue) => {
hooks[currentHook] = hooks[currentHook] || initialValue;
const hookIndex = currentHook;
const setState = (newState) => {
if (typeof newState === "function") {
hooks[hookIndex] = newState(hooks[hookIndex]);
} else {
hooks[hookIndex] = newState;
}
};
return [hooks[currentHook++], setState];
};
const useEffect = (callback, depArray) => {
const hasNoDeps = !depArray;
const prevDeps = hooks[currentHook] ? hooks[currentHook].deps : undefined;
const prevCleanUp = hooks[currentHook]
? hooks[currentHook].cleanUp
: undefined;
const hasChangedDeps = prevDeps
? !depArray.every((el, i) => el === prevDeps[i])
: true;
if (hasNoDeps || hasChangedDeps) {
if (prevCleanUp) prevCleanUp();
const cleanUp = callback();
hooks[currentHook] = { deps: depArray, cleanUp };
}
currentHook++;
};
const MyReact = {
render(Component) {
const instance = Component();
instance.render();
currentHook = 0;
return instance;
},
};
MyReact.useState = useState;
MyReact.useEffect = useEffect;
export { useState, useEffect };
export default MyReact;
useRef()가 순수 자바스크립트 객체
값을 유지하지만 상태 변경을 트리거하지 않는 훅
컴포넌트가 리렌더링 되더라도 useRef에 저장된 값은 유지되지만 값이 변경되더라도 컴포넌트가 다시 렌더링 되지 않는다.
같은 메모리 주소를 갖고있기 때문에 자바스크립트의 === 연산이 항상 true 를 반환
const countRef = useRef(0);
countRef.current += 1
const inputRef = useRef(null);
inputRef.current.focus();
useRef를 사용해서 타이머 만들기
const [count, setCount] = useState(0)
const timerRef = useRef(null)
const startTimer = ()=>{
if(timerRef.current)return;
timerRef.current = setInterval(()=>{
setCount((prev)=> prev + 1)
},1000)
}
// 언마운트 시 타이머 정리
useEffect(()=>{
return () => clearInterval(timerRef.current);
},[])