Hook은 react 16.8에 새로 추가되었다. Hook을 이용하여 class를 작성할 필요가 없이 상태변화를 할 수 있게 되었다.
간단하게 react의 this.setState와 똑같이 동작하지만 하나 알아야될께, 우리는 destructing을 이용해서 useState함수 자체가 리턴하는 값에 대한 변수정의를 해주고 useState를 사용한다.
const [number, setNumber] = useState(0)
...
setNumber(2)
console.log(number)//2
여기서 number은 state의 값이되고, setNumber은 number의 상태를 변경시킬수있는 함수가 되게된다. useState는 이 2가지를 리턴하게됨으로, 이제 우리는 setState를 훅스를 이용해서 할 수 있게 되었다.
componentDidUpdate과 비슷한 훅스이다. 간단하게 설명하면, 리액트는 렌더링 과정중에, 컴포넌트가 전달한 effect함수를 기억하고 돔의 변화를 처리한후 브라우저가 스크린에 그리고 난뒤 실행된다. 그래서 우리는 보통 일반적으로 이 함수안에 data fetching함수를 넣어놓는데, 이유는 먼저 렌더링 되고난후, effect함수안에서의 async/await이 진행되는것이고, 완료되면 다시 돔을 업데이트 해준다. 여기서 또하나의 중요한개념은, unmount가 되야한다. 예를들어 useEffect에서 eventListener함수가 포함되어있으면, unmount가 되지 않을시에 메모리에 게속 적재되어서, memory leak을 야기 할 수 있다. 고로 effect함수안에서 return을 통해서 언마운트를 시켜줘야한다.
React.useEffect(() =>{
console.log('called useEffect');
const handleClickOutside = (e) => {
if(!elRef?.current?.contains(e.target) && callback){
callback(e);
}
};
document.addEventListener('click', handleClickOutside, true);
return() => {
document.removeEventListener('click', handleClickOutside, true);
};
}, [callback, elRef]);
이 이펙트를 보면 코드는 이해가 가지만 마지막 [callback, elRef]가 뭔지 잘 모르겠다. 이것은 디펜던시 deps라고도 하며, 이펙트함수가 이 deps가 바뀔때만, 동작하게된다.
돔노드에서 reference를 담고있다. 바로 예제를 보자.
const menuRef = React.useRef();
...
return(
<div ref={menuRef}>
hello
</div>
)
이런식으로 돔 엘리먼트를 바로 reference에 담아서 이펙트함수에 변경된점을 감지 될 수 있게끔 할 수 있다. 그렇다면 current는 어떤식일까?
customHooks(ref,callback)
===>
useEffect(() => console.log, [ref, callback])
이런식의 함수에서 callback함수가 바뀌는것에 대해서는 effect를 실행하고싶지는 않지만, 커스텀훅스에서 useEffect를 실행 시켜주고싶을때는 커스텀훅스를 이런식으로 바꿀수있다.
customHooks(){
const callbackRef = React.useRef();
memoRef.current = callback
무슨말이냐 하면, useRef를 이용해서 객체를 생성해주고 그 객체안에 콜백함수를 담기때문에, useEffect가 콜백함수의 변화에 따라 매번 새로 렌더링 되지 않는다. 고로 렌더링시점을 굉장히 많이 줄일 수 있게 된다.