리액트에서 state라는 것은 상당히 중요한 개념이다.
state는 컴포넌트를 다시 렌더링하고 화면에 표시되는 것들을 바꿔준다.
useState hook을 이용하여.
따라서 가장 일반적인 형태의 managing state는 useState hook이다. 이를 이용하여 새로운 state를 만들어 useState를 쓰는 다른 컴포넌트와 연결할 수 있다.
useState가 실행되면 리액트가 관리하는 새로운 상태 변수를 만들게 되고 리액트는 이 변수가 어느 컴포넌트에 속하는지를 기억해둔다.
default 값을 사용해서 상태값을 초기화한다.
이후 초기화 이후에 state가 해당한 컴포넌트 함수를 호출(컴포넌트를 재평가)하는 과정에서 useState가 호출되면 새로운 state는 생성되지 않는다. 대신 리액트는 여기에서 이 컴포넌트에 대한 state가 이미 있다는 것을 알고 필요할 경우(호출, 재평가)에만 이 상태를 업데이트하게 된다.
따라서 한번 초기화가 되면 상태의 관리와 갱신만을 담당한다.
하지만 컴포넌트가 삭제되고 다시 연결되었다면 새로운 상태가 초기화될 수 있다
const toggleParagraphTrigger = useCallback(() => {
if(allowToggle){
setShowParagraph(prevShowParagraph => !showParagraph);
}
}, [allowToggle]);
굉장히 심플하게 App.js에 다음과 같은 코드가 있다. 이는 밑에 Button을 클릭하면 title을 바꿔주는 App이다.
이제 DemoList 컴포넌트를 보면 return값에 <h2>
태그가 있으니 DemoList 컴포넌트 전체가 다시 평가되는 것은 여지없는 사실이다 하지만 SQL문에서 성능에 가장 큰 영향을 미치는 것이 order by 이듯, 여기서도 정렬이 불필요하게 계속 된다면 사용자로 하여금 로딩이 오래걸리는 불쾌한 경험을 제공할 것이다. 이를 막고자 앞서는 useCallback
을 사용하였다. 하지만 useCallBack은 함수를 저장하지만 useMemo
는 모든 종류의 데이터를 저장할 수 있다. 여기서는 배열.
const 변수이름 = useMemo(() => {
return 저장하고싶은것(예 : 정렬된 배열)
}, [의존성])
이때 위 사진에서 의존성에 props이 아닌 item만 따로 꺼낸 이유는 props이 바뀔 때마다 전체 바뀌게 코드를 짠다면 도루묵이기 때문이다.
또 하나 신경써주어야할 것이 있는데 바로 props으로 넘어온 값이다. 앞서 포스팅 했듯 props에서 넘어온 값이 원시값이냐 참조값이냐에 따라 memo와 callback 훅을 골라서 사용했는데 이때 memo로 하겠다면 넘어오는 부모 컴포넌트에서의 return값의 props값을 또 확인해주어야한다.
그럼 모든 배열이나 데이터 마다 오래걸리지 않도록 걸어두면 어떨까?