Hook은 state와 생명 주기를 hook into(연동)하게 해주는 함수다.
컴포넌트 간 상태와 관련된 오직을 재사용하기 위해서 (HOC, render props)
복잡한 컴포넌트들을 이해하기 어려워서
class는 사람과 기계를 혼동시킨다(왜죠?)
state와 라이플 사이클 때문에 마치 생명처럼 클래스로부터 한번 instance가 생성되고 나면 독립적으로 움직일 수 있어서 사용했다. 반면 함수의 경우 한번 호출되고 메모리 상에서 사라지기 때문에 라이프 사이클이 불가능하다. 그렇다면 리액트야말로 객체 지향이 낳은 괴물인가.
클래스도 나름대로 문재가 많았기 때문에 hook이 등장했고 클로저를 사용해 함수를 좀비화시켜 hook이 널리 사용되기 시작했다.
hook은 언제나 최상위에 , 반복문/조건문/중첩 함수에서 hook을 실행하지 않는다.
react가 여러 훅들을 구분할 수 있는 유일한 정보는 훅이 사용된 순서 뿐이기 때문!
hook은 오직 react 함수 컴포넌트에서만 실행된다.
const [state, setState] = useState(initialState)
상태 유지 값과 그 값을 갱신하는 함수를 반환한다. 최초로 렌더링하는 동안, 반환된 state는 첫 번째 전달된 (initialState)의 값과 같다.
setState 함수는 state를 갱신할 때 사용한다. 새로운 state값을 받아 컴포넌트 리렌더링 큐에 등록한다.
useState는 항상 배열을 리턴한다. const item = useState(1)[0]이렇게 가능하다.
클로저는 자신이 생성될 때의 렉시컬 환경을 기억하는 함수다.
여기서 드는 의문은 함수는 상태를 저장하지 않는데, return되는 순간 죽음인데 상태를 어떻게 저장할까?
useState의 내부 모습인데 초기값을 받아서 useState 지역 변수 value에 할당한다. 내부 함수 getter()는 지역 변수 init을 바라보고 있다. 또 다른 내부 함수 setter()는 next 인자를 받아 value값을 수정한다. 이후 getter()를 호출하면 변경된 value의 값을 호출하게 된다.
두 함수는 배열 형태로 리턴되고 useState
를 사용할 때는 배열 구조분해 형태로 사용한다.
일반 함수라면 return되면 내부의 데이터들이 가비지 컬렉팅이 되지만 냄부 하수가 지역 변수를 참조하니까 사라지지 않는다!
외부로 노출된 getter, setter 함수를 통해 내부 변수에 지속적으로 접근하여 호출/재할당이 가능하다!
클래스로 하면 길게 쓸 것을 간단간단하게 쓸 수 있다.
React class의 componentDidMount 나 componentDidUpdate, componentWillUnmount와 같은 목적으로 제공되지만, 하나의 API로 통합된 친구.
useEffect(function);
useEffect(() => {}, [count]) // 의존성 배열 (배열 안에 담긴 값들을 추적, 그때 마다 업데이트)
기본적으로 동작은 모든 렌더링이 완료된 후에 수행된다.
useInput은 {value}를 리턴한다. 이제 name이란 변수를 만들고 useInput에 "Mr."를 주고 콘솔을 찍어보면
value를 키로 useInput의 인자를 value로 하는 객체가 만들어진다. 신기해!
input의 value에 값을 할당하면
요렇게 된다
신기하다...
onChange라는 함수를 만들어서 useInput에 넣는다. 그리고 onChange의 값을 리턴한다. onChange 함수는 매 순간 타켓의 이벤트를 감지한다.
이렇게 길게 쓸 것을 name이란 변수에 useInput()을 할당했으므로 풀어주기만 하면 된다.
참고 : 위코드 노션, 노마드 코더