react 19

MM·2025년 1월 22일

ArticleDigest

목록 보기
10/12
post-thumbnail

업데이트

react 18.3

18.2와 동일하지만, 리액트 19로의 업그레이드를 위한 사항이 추가된 버전

  • 지원중단 예정인 API에 대한 경고
  • 리액트 19를 사용하기 위해 필요한 변경사항



Actions

규칙에 따라 비동기 전환을 사용하는 함수
-> 보류중인 상태, 오류, 낙관적 업데이트 자동처를 위해 전환시 비동기 함수를 사용할 수 있게 되었다!

  • 보류 중인 상태: 작업은 요청 시작~최종 상태 업데이트 커밋될 때 자동으로 재설정되는 보류 상태를 제공합니다.

react 19 이전 코드

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

  const handleSubmit = async () => {
    setIsPending(true);
    const error = await updateName(name);
    setIsPending(false);
    if (error) {
      setError(error);
      return;
    }
    redirect("/path");
  };

  return (
    <div>
      <input value={name} onChange={(event) => setName(event.target.value)} />
      <button onClick={handleSubmit} disabled={isPending}>
        Update
      </button>
      {error && <p>{error}</p>}
    </div>
  );
}

useActionState

Actions의 일반적인 경우를 처리.
내부에 넣은 액션 함수는 래핑되어 submitAction으로 반환된다.

import { useActionState } from 'react';
import { action } from './actions.js';

//초기값, 현재값 둘다 props로 받음
function action(currentState, formData) {
  // ...
  return 'next state';
}

function MyComponent() {
  const [state, formAction, isPending] = useActionState(action, null);
  // SSR에서 하이드레이션이 끝나지 않았더라도 isPending을 이용하여 UI를 업데이트 가능
  return (
    <form action={formAction}>
      {/* ... */}
    </form>
  );
}

form 태그

action속성에 액션 함수를 전달하면 자동으로 연결된다!
-> 제출 후 양식이 자동으로 재설정된다!


useFormStatus

마지막 폼 제출의 상태 정보를 제공
-> form 내부에 렌더링한 컴포넌트에서 호출해야함! (최상위x)
-> 바로 상위 form에 대한 상태 정보만 반환한다!

import {useFormStatus} from 'react-dom';

function Submit() {
   // 현재 상태, 제출한 데이터, get이나 post, 상위 form에 전달한 함수
  const { pending, data, method, action } = useFormStatus();
  return <button disabled={pending}>Submit</button>
}
  
 export default function App() {
  return (
    <form action={action}>
      <Submit />
    </form>
  );
}

useOptimistic

비동기 요청이 진행되는 동안 최종 상태를 낙관적으로 표시
-> 실제로 작업을 완료하는 데 시간이 걸리더라도 사용자에게 즉시 작업의 결과를 표시할 수 있음!

낙관적 업데이트

서버로부터 실제 응답을 받기 전에 UI를 미리 업데이트하는 기법
-> 오류 발생시 낙관적 업데이트를 원래 값으로 자동으로 되돌림
-> 즉각적인 피드백 가능

import { useOptimistic } from 'react';

function AppContainer() {
  const [optimisticState, addOptimistic] = useOptimistic(initialState, updateFn);
  );
  
  const updateFn =  (currentState, optimisticValue) => {
    }
  const initialState = null;
}

optimisticValue

낙관적으로 사용할 값
작업이 대기 중 -> state와 동일
작업이 대기 아님 -> updateFn에서 반환된 값과 동일

addOptimistic

낙관적 업데이트가 있을 떄 호출하는 디스패치 함수
인자로 optimisticValue를 받아, updateFn 함수를 호출한다

예시

// 현재 상태
let state = {
  comments: ["First comment", "Second comment"],
};

// 상태를 업데이트하는 함수
function updateFn(state, optimisticValue) {
  // 낙관적으로 새 댓글을 추가
  return {
    ...state,
    comments: [...state.comments, optimisticValue],
  };
}

// addOptimistic 구현
function addOptimistic(optimisticValue) {
  state = updateFn(state, optimisticValue); // 상태 업데이트
  console.log("Updated state:", state); // 새로운 상태 출력
}

// 사용자가 새 댓글을 추가했을 때
addOptimistic("New comment");

// 결과
// Updated state: { comments: ["First comment", "Second comment", "New comment"] }



문서 메타데이터 지원

오.. 이제 헬멧을 안 써도 됨!
-> head section과 관련된 사항은 자동으로 문서 head 섹션으로 끌어올린다!

function BlogPost({post}) {
  return (
    <article>
      <h1>{post.title}</h1>
      <title>{post.title}</title>
      <meta name="author" content="Josh" />
      <link rel="author" href="https://twitter.com/joshcstory/" />
      <meta name="keywords" content={post.keywords} />
      <p>
        Eee equals em-see-squared...
      </p>
    </article>
  );
}



리소스 사전 로딩 api 지원

import { prefetchDNS, preconnect, preload, preinit } from 'react-dom'
function MyComponent() {
  preinit('https://.../script.js', {as: 'script' }) 
  preload('https://.../font.woff', { as: 'font' }) 
  preload('https://.../stylesheet.css', { as: 'style' }) 
  prefetchDNS('https://...') 
  preconnect('https://...') 
}



개선사항

에러 처리 방식 개선

onRecoverableError

React가 복구 가능한 오류를 감지했을 때 호출

onUncaughtError

Error Boundary에 의해 잡히지 않은 오류 (앱 전체 중단 가능성o)
window.reportError에 보고됨

onCaughtError

Error Boundary에 의해 잡힌 오류
console.error에 보고됨

const root = createRoot(container, {
   onRecoverableError: (error) => {
    console.warn("Recoverable error:", error);
  },
  onUncaughtError: (error, errorInfo) => {
    // ... 에러 리포트 로그
  },
  onCaughtError: (error, errorInfo) => {
    // ... 에러 리포트 로그
  },
});

React의 에러 처리 흐름

  1. 오류 발생 → React가 오류를 감지.
  2. Error Boundary 확인
    a. Error Boundary가 오류를 잡음: onCaughtError 호출
    b. Error Boundary가 없음: onUncaughtError 호출
  3. React가 복구 가능시 onRecoverableError 호출

StrictMode 변경

useMemo와 useCallback

개발 환경에서 Strict Mode로 인한 이중 렌더링이 발생할 때,
두 번째 렌더링에서 첫 번째 렌더링의 메모이제이션된 결과를 재사용하게 바뀜!


Suspense

이전 버전(React 18 이하)의 동작

컴포넌트가 Suspense 상태(예: 데이터 로딩 중)가 되면
-> 중단된 컴포넌트의 형제 컴포넌트들이 먼저 렌더링된다!
-> 형제 컴포넌트 렌더링이 끝나면, Suspense 경계의 fallback UI 표시
-> 즉, 형제 트리 전체 렌더링이 완료한 후에 fallback UI를 보여줬음.

React 19의 개선된 동작

Suspense 상태가 되면
-> 즉시 fallback UI가 표시
-> 이후 Suspense 경계 안 형제 컴포넌트들이 백그라운드에서 스케줄링 및 렌더링
-> 렌더링이 끝나면 fallback UI가 최종 콘텐츠로 대체

profile
중요한 건 꺾여도 그냥 하는 마음

0개의 댓글