react 19 beta가 2024년 4월 25일에 npm을 통하여 사용할 수 있게 되었습니다..
정식으로 나오지는 않았지만 무엇이 달라졌는지 살펴보도록 하겠습니다.
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>
);
}
액션의 일반적인 경우를 더 쉽게 처리할 수 있는 새로운 훅이 추가되었습니다.
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의 마지막 결과를 데이터로 반환하고, 보류 중인 상태라면 보류 중으로 반환합니다.
<form>
ActionsActions는 React 19의 새로운 <form>
기능과도 통합되었습니다. Actions를 사용하여 자동으로 양식을 제출하기 위해 요소의 props로 react-dom 함수를 전달하는 기능이 추가되었습니다.
<form action={actionFunction}/>
Action이 성공하면 React는 제어되지 않은 컴포넌트에 대해 자동으로 form을 재설정합니다. <form>
을 수동으로 재설정해야 하는 경우, 새로운 requestFormReset React DOM API를 호출할 수 있습니다.
디자인 시스템에서는 props를 컴포넌트까지 파고들지 않고도 해당 컴포넌트에 대한 정보에 엑세스해야하는 디자인 컴포넌트를 작성하는 것이 일반적입니다. 이 작업은 context를 통해 수행할 수 있지만, 일반적인 경우를 더 쉽게 만들기 위해 새로운 훅인 useFormStatus
가 추가되었습니다.
import {useFormStatus} from 'react-dom';
function DesignButton() {
const {pending} = useFormStatus();
return <button type="submit" disabled={pending} />
}
useFormStatus
는 form이 context 제공자인 것처럼 상위
데이터 변형을 수행할 때 흔히 사용되는 또 다른 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 값으로 다시 전환합니다.
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로 렌더링에서 리소스를 소비하는 더 많은 방법을 지원할 계획입니다.