React 19 맛보기

이한형·2024년 7월 2일
0

React 19 Beta

react 19 beta가 2024년 4월 25일에 npm을 통하여 사용할 수 있게 되었습니다..
정식으로 나오지는 않았지만 무엇이 달라졌는지 살펴보도록 하겠습니다.

Actions

React에서 데이터를 변형 후 다음 응답으로 상태 업데이트하는 방법을 사용합니다.
예를 들어, 사용자가 이름을 변경하기 위해 양식을 제출하면 API 요청을 한 다음 응답을 처리합니다.
과거에는 pending states(대기), errors(오류), optimistic updates(낙관적 업데이트), sequential requests(연속 요청)을 수동으로 처리하였습니다.

예를 들어, 보류 및 오류 상태를 다음과 같이 처리할 수 있습니다.

// Before Actions
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>
  );
}

React 19에서는 보류 중인 상태, 오류, form, 낙관적 업데이트를 자동으로 처리하기 위해비동기 함수를 사용할 수 있는 기능을 지원합니다.

에를 들어 useTransition을 사용하여 보류 상태를 처리할 수 있습니다.

// Using pending state from Actions
function UpdateName({}) {
  const [name, setName] = useState("");
  const [error, setError] = useState(null);
  const [isPending, startTransition] = useTransition();

  const handleSubmit = () => {
    startTransition(async () => {
      const error = await updateName(name);
      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>
  );
}

비동기 전환은 isPending상태를 즉시 true로 설정하고, 비동기 요청을 만들고, isPending전환 후 false로 전환합니다. 이를 통해 데이터가 변경되는 동안 현재 UI를 반응성 있고 상호 작용적으로 유지할 수 있습니다.

Actions를 기반으로 React 19는 useOptimistic을 통해 낙관적 업데이트를 관리하고, useActionState를 이용하여 일반적인 사례를 처리하는 새로운 hook이 추가되었습니다.

React 19에서는 위의 예를 다음과 같이 단순화할 수 있습니다.

// Using <form> Actions and useActionState
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 null;
    },
    null,
  );

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

useActionState

액션의 일반적인 경우를 더 쉽게 처리할 수 있는 새로운 훅이 추가되었습니다.

const [error, submitAction, isPending] = useActionState(
  async (previousState, newName) => {
    const error = await updateName(newName);
    if (error) {
      // You can return any result of the action.
      // Here, we return only the error.
      return error;
    }

    // handle success
    return null;
  },
  null,
);

useActionState는 Action을 하는 함수를 인자로 받고, 래핑된 Action을 반환합니다. 래핑된 Action이 호출되면 useActionState는 Action의 마지막 결과를 데이터로 반환하고, 보류 중인 상태라면 보류 중으로 반환합니다.

React DOM: <form> Actions

Actions는 React 19의 새로운 <form> 기능과도 통합되었습니다. Actions를 사용하여 자동으로 양식을 제출하기 위해 요소의 props로 react-dom 함수를 전달하는 기능이 추가되었습니다.

<form action={actionFunction}/>

Action이 성공하면 React는 제어되지 않은 컴포넌트에 대해 자동으로 form을 재설정합니다. <form>을 수동으로 재설정해야 하는 경우, 새로운 requestFormReset React DOM API를 호출할 수 있습니다.

useFormStatus

디자인 시스템에서는 props를 컴포넌트까지 파고들지 않고도 해당 컴포넌트에 대한 정보에 엑세스해야하는 디자인 컴포넌트를 작성하는 것이 일반적입니다. 이 작업은 context를 통해 수행할 수 있지만, 일반적인 경우를 더 쉽게 만들기 위해 새로운 훅인 useFormStatus가 추가되었습니다.

import {useFormStatus} from 'react-dom';

function DesignButton() {
  const {pending} = useFormStatus();
  return <button type="submit" disabled={pending} />
}

useFormStatus 는 form이 context 제공자인 것처럼 상위

의 상태를 읽습니다.

UseOptimistic

데이터 변형을 수행할 때 흔히 사용되는 또 다른 UI 패턴은 비동기 요청이 진행되는 동안 최종 상태를 낙관적으로 표시하는 것입니다. React 19에서는 이를 더 쉽게 하기 위해 useOptimistic이라는 새로운 훅이 추가되었습니다.

function ChangeName({currentName, onUpdateName}) {
const [optimisticName, setOptimisticName] = useOptimistic(currentName);

const submitAction = async formData => {
  const newName = formData.get("name");
  setOptimisticName(newName);
  const updatedName = await updateName(newName);
  onUpdateName(updatedName);
};

return (
  <form action={submitAction}>
    <p>Your name is: {optimisticName}</p>
    <p>
      <label>Change Name:</label>
      <input
        type="text"
        name="name"
        disabled={currentName !== optimisticName}
      />
    </p>
  </form>
);
}

useOptimistic hook은 updateName 요청이 진행되는 동안 optimisticName을 즉시 렌더링합니다. 업데이트가 완료되거나 오류가 발생하면 React는 자동으로 currentName 값으로 다시 전환합니다.

use

React 19에서는 렌더링에서 리소스를 읽을 수 있는 새로운 API가 도입되었습니다.. use
예를 들어, use 중인 프로비저닝을 읽으면 프로비저닝이 해결될 때까지 React가 일시 중단됩니다.

import {use} from 'react';

function Comments({commentsPromise}) {
// `use` will suspend until the promise resolves.
const comments = use(commentsPromise);
return comments.map(comment => <p key={comment.id}>{comment}</p>);
}

function Page({commentsPromise}) {
// When `use` suspends in Comments,
// this Suspense boundary will be shown.
return (
  <Suspense fallback={<div>Loading...</div>}>
    <Comments commentsPromise={commentsPromise} />
  </Suspense>
)
}

use API는 후크와 유사하게 렌더링에서만 호출할 수 있습니다. 후크와 달리 use은 조건부로 호출할 수 있습니다. 향후에는 use로 렌더링에서 리소스를 소비하는 더 많은 방법을 지원할 계획입니다.

profile
풀스택 개발자를 지향하는 개발자

0개의 댓글