리액트의 랜더링 방식은 우리가 알고 있는 함수(컴포넌트)가 virtualDom(객체)에서
실제 dom으로 가는 flow 방식이다.
만약 이 절차를 무시하고 실제 dom에 접근하기 위해서는 useRef 라는 hooks을 사용 해야한다.
컴포넌트 마다 fiber Node 라는 공간이 있는데,
이 공간은 후에 useState/useMemo/useCallback과 같은 훅의 데이터들이 저장되는 공간이다.
내가 리액트를 공부하면서 느낀점은 크게 이렇게 3가지 라고 생각한다.
- state의 활용
- 리랜더링
- 데이터 주고 받기
state는 어떤 변수의 데이터가 변했을 때 새로고침을 하지 않아도 실시간으로 값을 업데이트 해주어 변경해주게 된다.
처음에는 setState를 이용해서 데이터를 바꿔준 후
바로 다음 줄에, 바꾼 state를 활용하는 코드를 작성하는 동기적 코드를 짰었다.
🚫 하지만 콘솔을 찍어보니 state의 값은 업데이트 되기 전 값이였고 원하는대로 함수가 실행되지 않았다.
조금 알아보니 state의 값을 바꿔주는 setState는 비동기로 처리되고 있었고,
비동기로 처리 될 동안 바로 밑에서 동기적으로 코드를 처리해도 비동기처리가 완료되지 않아 안되던 것이였다.
이 처리는 리액트에서는 리랜더링이라는 기법을 이용하여 데이터가 업데이트 될 때마다 랜더링을 다시 해주게끔 설정되어 있었는데,
state를 바꾸는 setState 코드와 state를 활용하는 코드를 한 함수에 같이 쓰게 되면 함수가 다 끝난 이후에 재 랜더링을 실행하기 때문에 업데이트 이전 데이터를 활용하게 될 수 밖에 없었다.
이를 해결하려고 나온 것이 useEffect이며, useEffect는 첫 랜더링과 의존성을 걸고 있는
함수나 값이 바뀔 때 재 실행된다.
useState의 작동 과정
첫 랜더링 : useState에 기본값이 fiber Node에 저장
setState : setState로 이뤄지는 값을 >>> fiber Node(데이터 변경 감지) >> Rerendering
리액트에서는 State의 값이 변경 될 때 모든 변수나 함수 그리고 가상돔을 다시 그려준다.
이걸 리 랜더링이라고 하는데, a부터 z까지의 state가 존재하고 a,b State만 업데이트가 되야 하는 상황에 c부터 z까지의 랜더링이 다시 일어날 필요는 없다.
이는 불필요한 작업이라고 인식 될 수 있으며, 어플리케이션의 속도를 느리게 할 수 있기 때문에
이를 해결법으로 나온 것이 useMemo와 useCallback이다.
useMemo와 useCallback은 둘 다 현재 상태를 기억하는 함수인데,
useMemo는 return으로 꼭 값을 반환해야 하고, useCallback은 무조건적으로
값을 return 하지 않아도 되는 것 같다.
React memo
React.memo는 컴포넌트 자체에 메모제이션을 하는 것인데,
React.memo를 지정해도 리랜더링 되는 일이 간간히 일어나고 있다.
컴포넌트 내부에 상태가 변경되거나 참조 타입의 코드들이 때문이다.
밑에 있는 코드들은 메모제이션을 설정 해줘야 변경되지 않은 이전 값을 참조 할 수 있다.
- 객체
- 배열
- 함수
- 클래스
리액트를 사용하면서 컴포넌트간의 데이터 전송을 해야할 때가 있는데,
그때 props 라는 것을 사용하고, 이는 보통 부모 컴포넌트에서 자식 컴포넌트로 보내는 편이다.
이때 변수뿐만 아니라 함수나 setState를 보낼 수도 있다.
그리고, 많은 자식 컴포넌트에서 같은 데이터를 props로 받고 싶어 할 때는
context API를 통해 전역 state로 만들 수도 있다.