こんにちは!今回はReact 19で新しく追加・改善されたフックについて詳しく見ていきましょう。
目次
useActionState
useActionState
はReact 19で新しく導入されたフックで、サーバーアクションの状態を管理するために使用されます。
定義
サーバーアクションの実行状態と結果を追跡・管理できるフックです。
React 19以前のコード
以前は、サーバーアクションの状態を手動で管理する必要がありました:
function TodoForm() {
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(null);
async function handleSubmit(formData) {
setIsLoading(true);
try {
await addTodo(formData);
} catch (err) {
setError(err);
} finally {
setIsLoading(false);
}
}
return (
<form action={handleSubmit}>
{isLoading && <p>読み込み中...</p>}
{error && <p>エラーが発生しました:{error.message}</p>}
{/* フォームの内容 */}
</form>
);
}
React 19でのコード
function TodoForm() {
const [addTodoState, addTodo] = useActionState(async (formData) => {
'use server';
// サーバーアクションのロジック
});
return (
<form action={addTodo}>
{addTodoState.pending && <p>読み込み中...</p>}
{addTodoState.error && <p>エラーが発生しました:{addTodoState.error.message}</p>}
{/* フォームの内容 */}
</form>
);
}
useOptimistic
useOptimistic
は、ユーザーインターフェースを即座に更新しながら、バックグラウンドで実際の更新を処理する楽観的UIパターンを実装するために使用されます。
定義
現在の状態と楽観的更新のための関数を受け取り、即座にUIを更新するフックです。
React 19以前のコード
function TodoList() {
const [todos, setTodos] = useState([]);
async function handleComplete(todoId) {
// UIがサーバーレスポンスを待つ必要がある
await completeTodo(todoId);
const updatedTodos = await fetchTodos();
setTodos(updatedTodos);
}
return (
<ul>
{todos.map(todo => (
<li key={todo.id}>
<button onClick={() => handleComplete(todo.id)}>
{todo.completed ? '完了' : '未完了'}
</button>
</li>
))}
</ul>
);
}
React 19でのコード
function TodoList() {
const [todos, setTodos] = useState([]);
const [optimisticTodos, addOptimisticTodo] = useOptimistic(
todos,
(state, newTodo) => {
return state.map(todo =>
todo.id === newTodo.id
? { ...todo, completed: !todo.completed }
: todo
);
}
);
async function handleComplete(todoId) {
// UIが即座に更新される
addOptimisticTodo({ id: todoId, completed: true });
await completeTodo(todoId);
}
return (
<ul>
{optimisticTodos.map(todo => (
<li key={todo.id}>
<button onClick={() => handleComplete(todo.id)}>
{todo.completed ? '完了' : '未完了'}
</button>
</li>
))}
</ul>
);
}
useTransition
useTransition
はReact 18で導入され、React 19でさらに改善されました。
定義
UI更新の優先順位を指定してユーザー体験を向上させるフックです。
React 19でのコード
- サーバーコンポーネントとの統合強化
- 自動エラーバウンダリー処理
- パフォーマンスの最適化
function SearchResults() {
const [isPending, startTransition] = useTransition();
const [searchQuery, setSearchQuery] = useState('');
function handleSearch(e) {
startTransition(() => {
setSearchQuery(e.target.value);
});
}
return (
<div>
<input onChange={handleSearch} />
{isPending ? (
<p>検索中...</p>
) : (
<ResultsList query={searchQuery} />
)}
</div>
);
}
useFormStatus
useFormStatus
はフォームの送信状態を追跡する新しいフックです。
定義
フォームの送信状態(pending、submittingなど)を追跡・管理します。
React 19以前のコード
function SubmitButton() {
const [isSubmitting, setIsSubmitting] = useState(false);
async function handleSubmit(e) {
setIsSubmitting(true);
try {
await submitForm(e);
} finally {
setIsSubmitting(false);
}
}
return (
<button disabled={isSubmitting}>
{isSubmitting ? '送信中...' : '送信'}
</button>
);
}
React 19でのコード
function SubmitButton() {
const { pending } = useFormStatus();
return (
<button disabled={pending}>
{pending ? '送信中...' : '送信'}
</button>
);
}
use
use
フックは、PromiseやContextをより柔軟に使用できるようにする新しいフックです。
定義
PromiseやContextをコンポーネント内のどこでも使用できるようにするフックです。
React 19以前のコード
function UserProfile({ userPromise }) {
const [user, setUser] = useState(null);
useEffect(() => {
userPromise.then(data => setUser(data));
}, [userPromise]);
if (!user) return <p>読み込み中...</p>;
return <h1>こんにちは、{user.name}さん!</h1>;
}
React 19でのコード
function UserProfile({ userPromise }) {
const user = use(userPromise);
return <h1>こんにちは、{user.name}さん!</h1>;
}
結論
React 19は、サーバーコンポーネントとの統合、フォーム処理、状態管理など、様々な領域で開発者体験を大きく改善しました。特にuseActionState
やuseFormStatus
などの新しいフックは、サーバー状態の管理をより簡単にし、useOptimistic
はより良いユーザー体験を提供するのに役立ちます。
これらの変更により、Reactアプリケーションの開発がより効率的で直感的になり、特にサーバーコンポーネントに関連する機能が大幅に強化されたことは注目に値します。