20230211 [react] - react hook2

lionloopy·2023년 2월 11일
0

리액트

목록 보기
8/18

리렌더링

리렌더링의 발생 조건

  • 컴포넌트에서 state가 바뀌었을 때
  • 컴포넌트가 내려받은 props가 변경되었을 때
  • 부모 컴포넌트가 리렌더링 된 경우 자식 컴포넌트는 모두 리렌더링된다.

최적화
:불필요한 리렌더링을 줄이기 위한 작업이다.
이때문에 나온 hook ▼

  • React.memo: 컴포넌트를 캐싱
  • useCallback: 함수를 캐싱
  • useMemo: 값(value)을 캐싱

React.memo

:컴포넌트를 메모에 저장해두고 필요할 때 가져다 쓰게 된다. 이렇게 하면 부모 컴포넌트의 state 변경으로 인해 props의 변경이 일어나지 않는 한 컴포넌트는 리렌더링이 되지 않는다.

기본 코드

export default React.memo(box1)

App.js

function App() {
  const [count, setCount] = useState(0);

  const plusCount = () => {
    setCount(count + 1);
  };
  const miunsCount = () => {
    setCount(count - 1);
  };

  return (
    <div>
      <h3>카운트 예제</h3>
      <p>현재 카운트 : {count}</p>
      <button onClick={plusCount}>+</button>
      <button onClick={miunsCount}>-</button>
      <div style={{ display: "flex" }}>
        <Box1 />
        <Box2 />
        <Box3 />
      </div>
    </div>
  );
}

버튼을 클릭하면 카운트가 올라가고 내려가는 예제에서,
박스 세개를 자식 컴포넌트로 가져와 품었다. 그런데 카운트를 올리고 내릴 때 마다 자식 컴포넌트들인 박스들도 렌더링이 계속 된다. 이것을 방지하기 위해 export할 때 각 컴포넌트에게 React.memo를 활용한다.

useCallback

:React.memo는 컴포넌트를 메모리화 했다면, useCallback은 인자로 들어오는 함수를 메모화한다.

기본 코드

const initCount = useCallback(() => {
  setCount(0);
  }, []);

의존성 배열을 넣어주었기 때문에 initCount의 기능은 변하지 않는다.
(배열이 비어 있으면 어떤 값이 변하던지 간에 화면이 처음 로딩될 때만 작동한다.)

function App() {
  const [count, setCount] = useState(0);

  const plusCount = () => {
    setCount(count + 1);
  };
  const miunsCount = () => {
    setCount(count - 1);
  };

  const initCount = () => {
    setCount(0) 
  }

  return (
    <div>
      <h3>카운트 예제</h3>
      <p>현재 카운트 : {count}</p>
      <button onClick={plusCount}>+</button>
      <button onClick={miunsCount}>-</button>
      <div style={{ display: "flex" }}>
        <Box1 initCount={initCount} />
        <Box2 />
        <Box3 />
      </div>
    </div>
  );
}

App.js에서 Box1이라는 자식 컴포넌트에게 initCount라는 props를 전달한다.
이때 함수가 전달되므로 App.js가 렌더링 될 때 Box1도 계속해서 렌더링이 된다.
이것을 막기 위해 useCallback으로 initCount 함수를 감싼다.

useMemo

:React.memo는 컴포넌트를 메모화했다면, useCallbcak은 함수를 메모화하고, useMemo는 value값을 메모화한다.

기본 코드

const value = 반환할 함수() //기본

const value = useMemo(() => { //적용 후
  return 반환할 함수()}, [])

컴포넌트가 무거울 때

function Heavy() {
  const [count, setCount] = useState(0);

  const heavyWork = () => {
    for(let i=0; i<10000; i++){
        return 100;
    }
  }
  const value = heavyWork()

  return (
    <div>
      <p>나는 무거워</p>
      <button
        onClick={() => {
          setCount(count + 1);
        }}
      >
        {" "}
        +++{" "}
      </button>
      {count}
    </div>
  );
}

count를 누르면 setCount가 되면서 리렌더링이 된다. 리렌더링이 되면서 value가 다시 호출되고, 그 value변수는 heavyWork() 함수를 호출해서 무거운 heavyWork함수가 계속해서 렌더링 될 때 마다 돌아가게 된다.

useMemo적용

const value = heavyWork() //적용 전
cont value = useMemo(() => heavyWork(),[]) //적용 후

이렇게 하면 useMemo의 return값을 한 번 저장해놓고, 변하지 않을 때 까지 쓰는 것이다.

의존성 배열
:의존성 배열을 넣어도 필요없는 부분을 클릭했을 때 리렌더링 되는 경우가 있다. 이 때는 필요한 부분에 useMemo를 넣어주면 된다.

하지만 useMemo는 너무 많이 쓰면 효율이 떨어지게 되므로 주의해서 사용해야 한다.

생명주기

:리액트 컴포넌트는 각각 mount -> update -> unmount의 과정을 거친다.
모든 컴포넌트에는 각각의 생명주기가 존재하고, 각 생명주기에 맞는 메서드들이 있다.

Mount
:컴포넌트가 생성될 때

  • constructor: 컴포넌트가 맨 처음 만들어질 때 호출
  • getDerivedStateFromPros: 부모 컴포넌트로부터 props를 전달받았을 때, state에 값을 일치시키는 역할을 하는 메서드. 리렌더링 될 때도 호출된다.
  • render: 최초 mount가 준비되면 호출되는, 렌더링 하는 메서드
  • componentDidMount: 컴포넌트가 브라우저에 표시가 된 후 호출하는 메서드

Update
:컴포넌트가 갱신될 때

  • getDerivedStateFromProps: 부모 컴포넌트로부터 props를 전달받을 때, state에 값을 일치시키는 역할을 하는 메서드
  • shouldComponentUpdate: 리렌더링 여부 판단. 함수 호출 결과가 true인 경우에는 리렌더링 진행, false인 경우에는 리렌더링 하지 않는다. 함수형 컴포넌트에서 memo,useMemo,useCallback이 역할을 대신한다.
  • render: 변경사항 반영이 다 되어 준비 완료 되면 호출되는, 렌더링 하는 메서드
  • getSnapshotBeforeUpdate: 컴포넌트에 변화가 일어나기 직전 DOM의 상태를 저장한다.
  • componentDidUpdate: 컴포넌트 업데이트 작업 완료 후 호출한다.

Unmount
:컴포넌트가 DOM에서 제거될 때

  • componentWillUnmount: 컴포넌트가 사라지기 전 호출되는 메서드. useEffect의 return과 동일하다.

virtual DOM

:리액트는 가상돔을 사용해서 원하는 화면을 브라우저에 그려준다.

DOM
:웹페이지는 수많은 컴포넌트로 구성이 되어 있다. 그 페이지를 document라고 하고, 페이지를 이루는 컴포넌트를 element라고 한다.
DOM은 이 엘리먼트를 tree형태로 표현한 것이다.

트리의 요소 하나하나를 노드라고 부르고, 각각의 노드는 해당 노드에 접근과 제어할 수 있는 API를 제공한다.
(API = html요소에 접근해서 수정할 수 있는 함수)

virtual DOM
:리액트는 가상돔을 이용해서 더 효율적으로 수행한다.
실제돔을 객체 형태로 메모리에 저장한다.

ex)인스타그램 좋아요 기능
1.리액트는 좋아요를 누르기 전(화면이 갱신되기 전) 구조와, 좋아요를 누른 후(화면이 갱신된 후) 2가지의 가상돔을 가지고 있다.
2.state가 변경되면 두가지 가상돔을 비교해서 어느 엘리먼트에서 변화가 일어났는지 비교한다.
3.파악이 끝나면 그 부분만 실제돔에 적용시킨다. 적용할 때 모두 모아 한 번에 적용한다.(paint) 좋아요의 하트만 바뀌는 것이 아닌 좋아요 옆에 찍힌 좋아요 갯수도 늘려준다.

profile
Developer ʕ ·ᴥ·ʔ ʕ·ᴥ· ʔ

0개의 댓글