본문 바로가기
TIL

[React] React 19 내용 정리

by ye-jji 2024. 12. 2.

React 컴파일러

- React 코드를 최적화된 JavaScript로 변환하여 성능을 크게 향상
- 컴포넌트 렌더링을 자동으로 관리하여 수동 상태 및 UI 업데이트가 필요 없어짐
- useMemo, useCallback, memo 등의 수동 최적화 필요성을 줄임

 

서버 컴포넌트

- 컴포넌트를 서버에서 미리 렌더링하여 초기 페이지 로드 시간을 개선하고 SEO를 향상시킴
- 클라이언트로 전송되는 JavaScript 양을 줄여 성능을 개선

 

액션(Actions)

- 폼 제출 등의 데이터 변경 작업을 더 쉽게 처리할 수 있게 해줌
- 비동기 작업의 상태 관리를 자동화하여 개발자 경험을 개선

 

새로운 Hooks

- useOptimistic: 서버 응답 전 UI를 낙관적으로 업데이트함
- useFormStatus: 폼 제출 상태를 관리
- useFormState: 폼 상태를 관리
- use: 렌더링 중 리소스를 읽을 수 있는 새로운 API

 

로딩 최적화

- 백그라운드에서 이미지와 파일을 미리 로드하여 페이지 전환 시 대기 시간을 줄임
- 새로운 Resource Loading API (preload, preinit)를 제공

 

문서 메타데이터 지원

- 컴포넌트 내에서 직접 title, meta 태그 등을 렌더링할 수 있게 됨

 

 

이전 버전과 기능 비교

Actions와 Form 제출 처리

이전 구현 코드

function ChangeName({ name, setName }) {
  const [error, setError] = useState(null);
  const [isPending, setIsPending] = useState(false);

  const handleSubmit = async (event) => {
    event.preventDefault();
    setIsPending(true);
    try {
      const formData = new FormData(event.target);
      const newName = formData.get("name");
      const error = await updateName(newName);
      if (error) {
        setError(error);
      } else {
        setName(newName);
        // 리다이렉트 로직
      }
    } catch (err) {
      setError("An unexpected error occurred");
    } finally {
      setIsPending(false);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <input name="name" defaultValue={name} />
      <button type="submit" disabled={isPending}>
        {isPending ? "변경 중..." : "변경"}
      </button>
      {error && <p>{error}</p>}
    </form>
  );
}

 

React 19

function ChangeName({ name, setName }) {
  const [error, submitAction, isPending] = useActionState(
    async (previousState, formData) => {
      const error = await updateName(formData.get("name"));
      if (error) {
        return error;
      }
      redirect("/path");
    }
  );

  return (
    <form action={submitAction}>
      <input name="name" defaultValue={name} />
      <button type="submit" disabled={isPending}>
        변경
      </button>
      {error && <p>{error}</p>}
    </form>
  );
}

 

- React 19의 새로운 Actions 기능과 useActionState Hook을 사용

- useActionState는 폼 제출 로직, 에러 상태, 그리고 로딩 상태를 한 번에 관리

- 첫 번째 인자로 비동기 함수를 받아 폼 제출 로직을 처리

- 반환값으로 [error, submitAction, isPending]을 제공

- action={submitAction}을 통해 폼 제출 시 실행될 액션을 지정

- 이전 버전에서 필요했던 event.preventDefault()나 수동 상태 관리가 필요 없어짐

- 서버 사이드 렌더링과 더 잘 통합, 프로그레시브 인핸스먼트를 지원함

useFormStatus 기능

이전 구현 코드

function SubmitButton({ isPending }) {
  return (
    <button type="submit" disabled={isPending}>
      {isPending ? "제출 중..." : "제출"}
    </button>
  );
}

function Form() {
  const [isPending, setIsPending] = useState(false);

  const handleSubmit = async (event) => {
    event.preventDefault();
    setIsPending(true);
    try {
      // 폼 제출 로직
    } finally {
      setIsPending(false);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      {/* 폼 필드들 */}
      <SubmitButton isPending={isPending} />
    </form>
  );
}

 

React 19

import { useFormStatus } from "react-dom";

function SubmitButton() {
  const { pending } = useFormStatus();
  return (
    <button type="submit" disabled={pending}>
      {pending ? "제출 중..." : "제출"}
    </button>
  );
}

function Form() {
  const handleSubmit = async (formData) => {
    // 폼 제출 로직
  };

  return (
    <form action={handleSubmit}>
      {/* 폼 필드들 */}
      <SubmitButton />
    </form>
  );
}

 

- 새로운 useFormStatus Hook을 사용
- useFormStatus는 현재 폼의 제출 상태를 추적, pending 상태를 통해 폼이 제출 중인지 여부를 알 수 있음

- SubmitButton 컴포넌트는 폼의 상위 컴포넌트와 상태를 공유할 필요 없이 자체적으로 제출 상태를 관리함

- Form 컴포넌트는 action prop에 직접 핸들러 함수를 전달

- 이전 버전에서 필요했던 useState와 isPending 상태 관리가 필요 없어짐

- 코드가 더 선언적이고 간결해짐, 컴포넌트 간 결합도가 낮아짐.

 

출처:

https://ko.react.dev/blog/2024/04/25/react-19

 

React 19 RC – React

The library for web and native user interfaces

ko.react.dev