2019-07-14
그냥 아주 조금
useState
는 새 state를 기존 state와 merge하지 않음!
기존 setState
와 다른 중요한 점이다. 기존 state를 새 state로 갈아치운다. (물론 useState 호출하며 짝지어 선언한 state만 건드린다)
선언한 state 변수를 유지시켜준다.
어찌보면 당연한, 내부 동작이라고 볼 수 있다. 렌더마다 컴포넌트 함수가 새로 실행되므로 어떤 장치가 없다면 안에 선언한 state 변수의 내용이 계속해서 초기화될 수도 있는데, 이 부분을 우리가 기대하는 대로 동작하게 하는 것이다.
함수형 컴포넌트 안에 선언한 함수는 매 렌더마다 새로 생성된다. (클래스 컴포넌트와 다르게, return이 곧 render될 view라는 점을 생각해보자.)
이벤트 핸들러 함수는 텍스트 인풋이나 마우스 움직임, 스크롤 변화 등 연속적이고 빠르게 발생하는 이벤트를 처리하곤 하는데, 이 이벤트에 의한 수많은 렌더링 시점에 함수를 새로 생성하는 것은 분명한 비효율이다.
useCallback
를 사용하면, 특정 시점에만 함수를 선언해놓고 이용할 수 있게 된다.
다시 말해, 위에 언급한 동일 함수의 반복 생성을 막아준다.
useCallback
을 사용해 이벤트 핸들러를 선언하는 습관을 들이는 것이 좋겠다.
로직에 해당하는 부분을 따로 묶어 또다른 훅처럼 사용하는 패턴을 말한다.
import React, { useState } from "react";
const useClickCount = initialClicks => {
const [clicks, setClicks] = useState(initialClicks);
const increment = () => setClicks(clicks + 1);
return [clicks, increment];
};
const Counter = () => {
const [clicksA, incrementA] = useClickCount(0);
const [clicksB, incrementB] = useClickCount(0);
return (
<>
<p>{clicksA} A clicks <button onClick={incrementA}>Click A</button></p>
<p>{clicksB} B clicks <button onClick={incrementB}>Click B</button></p>
</>
);
}
출처: https://medium.com/trabe/react-16-7-753c61ca7a1e
간단한 예제라 custom hooks가 뭔지 알기엔 좋다.
custom hooks를 잘 만들어 활용하려면 머릴 좀 굴려야겠다.
이건 좀 신기해서 퍼옴
import React, { useState, useEffect } from "react";
const SizeWrapper = ({ children }) => {
const [size, setSize] = useState({ height: window.innerHeight, width: window.innerWidth });
useEffect(() => {
const handleResize = () => setSize({ height: window.innerHeight, width: window.innerWidth });
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
return children(size);
}
<SizeWrapper>
{({ height, width }) => (
<>
<p>Height = {height}</p>
<p>Width = {width}</p>
</>
)}
</SizeWrapper>
출처: https://medium.com/trabe/react-16-7-753c61ca7a1e
children을 이렇게도 쓸 수 있구나!!
근데 가만보면 함수형 컴포넌트를 children으로 받은것과 같다.
아, 원래 이 코드의 요점은 useEffect
를 사용해 첫 렌더 시 이벤트 리스너를 달아줬고, cleanup function을 return하도록 작성해 unsubscribe에 쓸 수 있다는 것임.
(각각 componentDidMount
, componentWillUnmount
에 해당)
아래 그림은 Dan Abramov가 ReactConf2018 발표에 사용한 코드를 visualization한 것이다. (출처에 가면 gif로 볼 수 있다)
출처: https://twitter.com/prchdk/status/1056960391543062528
요지는, lifecycle method 안에 각각 뜯어져 있는 로직을 custom hooks 등을 이용해 묶어줄 수 있다는 것이고, 이렇게 만든 로직을 추출해 재사용할 수 있다는 것이다.
hooks의 규칙 두가지 적으며 마무리한다.
위 규칙들은 공식 lint가 있으니 적용해 코딩하는것이 이득이다.