React 공식문서 이해하기 (12)

Syoee·2023년 11월 20일
0

React

목록 보기
12/30
post-thumbnail

Chapter 2. Adding Interactivity

#4 스냅샷으로서의 state

학습 목차

1. state를 설정하면 렌더링이 트리거된다.
2. 렌더링은 그 시점의 스냅샷을 찍는다.
3. 시간 경과에 따른 state


KeyNote

  • state 변수는 읽고 쓸 수 있는 일반 JavaScript 변수처럼 보일 수 있다.
  • 하지만 state는 스냅샷처럼 동작한다.
  • state 변수를 설정해도 이미 가지고 있는 state 변수는 변경되지 않고, 대신 리렌더링이 실행된다.

1. state를 설정하면 렌더링이 트리거된다.

  • 클릭과 같은 사용자 이벤트에 반응하여 사용자 인터페이스가 직접 변경된다고 생각할 수 있습니다. React에서는 이 멘탈 모델과는 조금 다르게 작동한다.
  • 이전 페이지에서 state를 설정하면 React에 리렌더링을 요청하는 것을 보았습니다.
  • 즉, 인터페이스가 이벤트에 반응하려면 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) {
  // ...
}
  • “send”를 누르면 setIsSent(true)가 React에 UI를 다시 렌더링하도록 지시한다.
  • 버튼을 클릭하면 다음과 같은 일이 발생한다.
    1. onSubmit 이벤트 핸들러가 실행된다.
    2. setIsSent(true)isSenttrue로 설정하고 새 렌더링을 에 대기시킨다.
    3. React는 새로운 isSent 값에 따라 컴포넌트를 다시 렌더링한다.

2. 렌더링은 그 시점의 스냅샷을 찍는다.

  • “렌더링”이란 React가 컴포넌트, 즉,함수를 호출한다는 뜻이다.
  • 해당 함수에서 반환하는 JSX는 시간상 UI의 스냅샷과 같다.
  • prop, 이벤트 핸들러, 로컬 변수는 모두 렌더링 당시의 state를 사용해 계산된다.
  • 사진이나 동영상 프레임과 달리 반환하는 UI ‘스냅샷’은 대화형이다.
    • 여기에는 input에 대한 응답으로 어떤 일이 일어날지 지정하는 이벤트 핸들러와 같은 로직이 포함된다.
    • 그러면 React는 이 스냅샷과 일치하도록 화면을 업데이트하고 이벤트 핸들러를 연결한다.
    • 결과적으로 버튼을 누르면 JSX에서 클릭 핸들러가 발동된다.
  • React가 컴포넌트를 다시 렌더링할 때
    1. React가 함수를 다시 호출합니다.
    2. 함수가 새로운 JSX 스냅샷을 반환합니다.
    3. 그러면 React가 반환한 스냅샷과 일치하도록 화면을 업데이트합니다.


Illustrated by Rachel Lee Nabors

  • 컴포넌트의 메모리로서 state는 함수가 반환된 후 사라지는 일반 변수와 다르다.
  • state는 실제로 함수 외부에 마치 선반에 있는 것처럼 React 자체에 “존재”한다.
  • React가 컴포넌트를 호출하면 특정 렌더링에 대한 state의 스냅샷을 제공한다.
  • 컴포넌트는 해당 렌더링의 state 값을 사용해 계산된 새로운 props 세트와 이벤트 핸들러가 포함된 UI의 스냅샷을 JSX에 반환한다.


Illustrated by Rachel Lee Nabors

3. 시간 경과에 따른 state

import { useState } from 'react';

export default function Counter() {
  const [number, setNumber] = useState(0);

  return (
    <>
      <h1>{number}</h1>
      <button onClick={() => {
        setNumber(number + 5);
        alert(number);
      }}>+5</button>
    </>
  )
}
  • 이전부터 치환 방법을 사용하면 알림에 “0”이 표시된다는 것을 짐작할 수 있다.
setNumber(0 + 5);
alert(0);
  • 하지만 경고에 타이머를 설정하여 컴포넌트가 다시 렌더링된 후에만 발동하도록 하면 어떨까?
import { useState } from 'react';

export default function Counter() {
  const [number, setNumber] = useState(0);

  return (
    <>
      <h1>{number}</h1>
      <button onClick={() => {
        setNumber(number + 5);
        setTimeout(() => {
          alert(number);
        }, 3000);
      }}>+5</button>
    </>
  )
}
  • 대체 방법을 사용하면 알림에 전달된 state의 ‘스냅샷’을 볼 수 있다.
setNumber(0 + 5);
setTimeout(() => {
  alert(0);
}, 3000);
  • React에 저장된 state는 알림이 실행될 때 변경되었을 수 있지만, 사용자가 상호작용한 시점에 state 스냅샷을 사용하는 건 이미 예약되어 있던 것이다.
  • state 변수의 값은 이벤트 핸들러의 코드가 비동기적이더라도 렌더링 내에서 절대 변경되지 않는다.
    해당 렌더링의 onClick 내에서, setNumber(number + 5)가 호출된 후에도 number의 값은 계속 0이다.
    이 값은 컴포넌트를 호출해 React가 UI의 “스냅샷을 찍을” 때 “고정”된 값이다.
  • 다음은 이벤트 핸들러가 타이밍 실수를 줄이는 방법을 보여주는 예이다.
    아래는 5초 지연된 메시지를 보내는 양식이다.
    • “보내기” 버튼을 눌러 앨리스에게 “안녕하세요”를 보낸다.
    • 5초 지연이 끝나기 전에 “받는 사람” 필드의 값을 “Bob”으로 변경한다.
import { useState } from 'react';

export default function Form() {
  const [to, setTo] = useState('Alice');
  const [message, setMessage] = useState('Hello');

  function handleSubmit(e) {
    e.preventDefault();
    setTimeout(() => {
      alert(`You said ${message} to ${to}`);
    }, 5000);
  }

  return (
    <form onSubmit={handleSubmit}>
      <label>
        To:{' '}
        <select
          value={to}
          onChange={e => setTo(e.target.value)}>
          <option value="Alice">Alice</option>
          <option value="Bob">Bob</option>
        </select>
      </label>
      <textarea
        placeholder="Message"
        value={message}
        onChange={e => setMessage(e.target.value)}
      />
      <button type="submit">Send</button>
    </form>
  );
}
  • React는 하나의 렌더링 이벤트 핸들러 내에서 state 값을 “고정”으로 유지한다.
  • 코드가 실행되는 동안 state가 변경되었는지 걱정할 필요가 없다.

요약

  • state를 설정하면 새 렌더링을 요청한다.
  • React는 컴포넌트 외부에 마치 선반에 보관하듯 state를 저장한다.
  • ‘useState’를 호출하면 React는 해당 렌더링에 대한 state의 스냅샷을 제공한다.
  • 변수와 이벤트 핸들러는 다시 렌더링해도 “살아남지” 않습니다. 모든 렌더링에는 자체 이벤트 핸들러가 있다.
  • 모든 렌더링(과 그 안에 있는 함수)은 항상 React가 그 렌더링에 제공한 state의 스냅샷을 “보게” 된다.
  • 렌더링된 JSX에 대해 생각하는 것처럼 이벤트 핸들러에서 state를 정신적으로 대체할 수 있다.
  • 과거에 생성된 이벤트 핸들러는 그것이 생성된 렌더링 시점의 state 값을 갖는다.

React 공식 문서

https://react.dev/

React 비공식 번역 문서

https://react-ko.dev/

MDN

https://developer.mozilla.org/ko/

Wikipedia

https://ko.wikipedia.org/wiki/

profile
함께 일하고 싶어지는 동료, 프론트엔드 개발자입니다.

0개의 댓글

관련 채용 정보