프론트엔드✏️/개인공부

[react] 리액트 리렌더링

당근먹는하니 2023. 3. 2. 20:53
728x90
반응형

 

 학원 다닐 때 올린 ssr과 csr의 차이, ==와 === .. .등은 약간 의무적으로 올린 거였다.

단어에 익숙해진 건 좋았지만 실제로 머리에 남아있지 않았다. 그래서 이번엔 1시간 정도는 공부를 하고 그것에 대해 쓰려한다. 

 

 

 리액트에서 리렌더링이 일어나는 경우는?

1. props나 state가 업데이트 될 때 

 

2. 부모 컴포넌트가 리렌더링 될 때

     부모 컴포넌트가 리렌더링 되면 해당 컴포넌트와 그 하위 컴포넌트가 리렌더링 된다. 

 

3. context가 변경될 때

 

4. hook을 사용하여 상태를 관리할 때

     useState, useReducer 같은 훅을 사용할 때, 상태가 변경되면 해당 컴포넌트와 그 하위 컴포넌트가 리렌더링 된다.

 

5. ForceUpdate() 함수가 호출될 때

     ForceUpdate() 함수는 컴포넌트를 강제로 다시 렌더링한다. (해당 컴포넌트와 그 하위 컴포넌트 리렌더링 됨)

 

6. 화면 레이아웃이 변경될 때

     브라우저의 크기나 위치 등이 바뀌면 해당 컴포넌트와 그 하위 컴포넌트가 리렌더링 된다. 

 

 

 그럼 왜 상태(state)가 변경되면 리렌더링이 일어날까? 

(최소한의 업데이트만 실제 DOM에 반영하여 불필요한 리렌더링을 방지하기 위해 가상 DOM을 사용한다.)

상태(state)가 변경되면 가상 DOM에 변경된 내용을 반영한다. 그리고 기존의 DOM과 비교하여 변경된 부분만 찾아낸다. 그 이후엔 변경된 부분만 실제 DOM에 업데이트 한다! 

-> 가상 DOM이 변경된 내용을 실제 DOM에 반영하기 위해서 필요한 과정이다.

 

 

 현재 상태와 동일한 값이면 리렌더링 되지 않는다. -> setState에서 객체나 배열을 쓸 때 조심하기

동일한 값인지 판단할 땐 Object.is()를 사용한다. 

 

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Object/is#Description 

 

Object.is() - JavaScript | MDN

Object.is() 메서드는 두 값이 같은 값인지 결정합니다.

developer.mozilla.org

 

 

 state를 업데이트 했는데 console.log에 찍어보면 그대로야!

state는 스냅샷처럼 작동한다.

state가 업데이트 되면 그 새로운 값에 대한 렌더링이 요청된다. 그러나 이미 실행 중인 이벤트 핸들러안의 변수에는 영향을 미치지 않는다. 

 

 state가 스냅샷처럼 작동한다는 의미가 뭔지 모르겠다. 

예제를 따라해보면서 이해해보자... 

 

import { useState } from 'react';

export default function Form() {
  const [isSent, setIsSent] = useState(false);
  const [message, setMessage] = useState('Hi!');
  if (isSent) {
    return <h1>Your message is on its way!</h1>
  }
  return (
    <form onSubmit={(e) => {
      e.preventDefault();
      setIsSent(true);
      sendMessage(message);
    }}>
      <textarea
        placeholder="Message"
        value={message}
        onChange={e => setMessage(e.target.value)}
      />
      <button type="submit">Send</button>
    </form>
  );
}

function sendMessage(message) {
  // ...
}

input과 button이 있고 send를 누르면 isSent가 true로 set되면서 메세지가 뜬다. 

 

버튼을 클릭하면

 1. onSubmit의 이벤트 핸들러가 작동한다.

 2. setIsSent(true)가 isSent를 true로 바꾸고 리렌더링을 요청한다. 

 3. 새로운 isSent로 리렌더링 된다. 

 

 

 state와 rendering에 대해 좀 더 자세히 알아보자!

 

 사진이나 영화 프레임과 달리 스냅샷은 interactive하다고 함.

일단 내가 스냅샷이 뭔지 제대로 모르는 것 같아서 검색해봤다. 포즈를 잡고 찍는 사진이나 셀카 같은 게 아니라 어떤 걸 하는 순간을 포착해서 찍는 걸 스냅샷이라고 하는 것 같다. 

 input에 반응하여 발생하는 일을 지정하는 이벤트 핸들러 같은 로직을 포함한다고 한다. 

 

Rendering이란 무엇인가? 

-> 리액트가 함수인 컴포넌트를 호출하는 것을 의미함, props, state, 이벤트 핸들러, 변수는 렌더가 되는 그 시점으로부터 계산된다. 

 

리액트가 컴포넌트를 리렌더링 할 때

 1. 리액트가 함수를 다시 호출한다.

 2. 함수는 새로운 JSX 스냅샷을 리턴한다.

 3. 리액트는 그 스냅샷에 맞게 화면을 업데이트 한다. 

 

 

리액트야 state 업데이트 해다오,,리액트는 상태값을 업데이트 한 후 그것에 대한 스냅샷을 컴포넌트로 전달~~

 

 

const [number, setNumber] = useState(0);
...
<button onClick={() => {
  setNumber(number + 1);
  setNumber(number + 1);
  setNumber(number + 1);
}}>{number}</button>

이 버튼을 눌렀을 때 기대한 값은 3이지만! number는 1이다. 

 

왜냐면! setState는 다음 리렌더링시에 적용된다. 그래서 number는 아직 0이다. 그 상태에서 이벤트 핸들러 안의 두 번째 setNumber가 작동하면 setNumber(0 + 1) 과 같다. 그러나 이것 또한 다음 리렌더링시에 적용되기 때문에 number는 0이다. ...반복

 

 

<button onClick={() => {
        setNumber(number + 5);
        alert(number);
      }}>{number}</button>

setNumber() 뒤에 alert()으로 number를 보여주게 했다.

alert엔 0이 뜬다!

 

alert()이 setNumber() 앞에 있든 뒤에 있든 결과는 같다.

이미 스냅샷 찍어서 보냈기 때문!

 

 

 

https://beta.reactjs.org/learn/state-as-a-snapshot

 

State as a Snapshot

A JavaScript library for building user interfaces

beta.reactjs.org

 

 

https://beta.reactjs.org/reference/react/useState#ive-updated-the-state-but-logging-gives-me-the-old-value

 

useState

A JavaScript library for building user interfaces

beta.reactjs.org

 

728x90
반응형