useActionState
useActionState
란?useActionState
는 Next.js 13에서 도입된 서버 액션 클라이언트에서 사용할 수 있도록 도와주는 훅입니다. 이 훅은 서버에서 실행되는 비동기 작업을 클라이언트에서 쉽게 실행하고, 그 상태를 클라이언트와 서버 간에 동기화할 수 있게 해줍니다. useActionState
를 사용하면 폼 상태 관리뿐만 아니라, 서버 액션을 통해 클라이언트와 서버 간의 상태를 효율적으로 동기화할 수 있습니다.
useActionState
vs 기존 상태 관리useState
, useReducer
)일반적으로 React에서는 상태 관리와 서버와의 상호작용을 수동으로 처리합니다. 예를 들어, 서버에 데이터를 제출하거나 변경하려면, API 호출을 통해 서버에 요청을 보내고, 응답을 받은 후 클라이언트 상태를 업데이트 합니다. 이 과정에서는 서버와 클라이언트 간의 상태 동기화가 복잡하고, 여러 번의 상태 업데이트가 필요합니다.
import { useState } from 'react';
function MyComponent() {
const [state, setState] = useState({ submitted: false });
const [isSubmitting, setIsSubmitting] = useState(false);
const handleSubmit = async () => {
setIsSubmitting(true);
try {
const response = await fetch('/api/submit', { method: 'POST' });
if (response.ok) {
setState({ ...state, submitted: true });
}
} catch (error) {
console.error('Error submitting:', error);
} finally {
setIsSubmitting(false);
}
};
return (
<div>
<h1>{state.submitted ? 'Form Submitted!' : 'Form Not Submitted'}</h1>
<button onClick={handleSubmit} disabled={isSubmitting}>
{isSubmitting ? 'Submitting...' : 'Submit'}
</button>
</div>
);
}
❗ 복잡한 상태 관리: 서버 응답을 받은 후 상태를 수동으로 업데이트해야 하고, 그 과정에서 로딩 상태 처리, 에러 처리, 상태 업데이트를 모두 관리해야 하므로 코드가 복잡해질 수 있습니다.
❗ 상태 동기화의 어려움: 서버와 클라이언트 간의 상태 동기화를 수동으로 처리해야 하므로 에러가 발생할 가능성이 높고, 코드 중복이 발생할 수 있습니다.
useActionState
로 개선된 점useActionState
는 이러한 비동기 작업 처리와 상태 동기화를 자동으로 처리해줍니다. 이제 클라이언트에서 서버 액션을 호출하고, 그 결과로 발생하는 상태 변경을 자동으로 관리할 수 있습니다. 서버 액션을 클라이언트에서 쉽게 호출하고, 상태를 자동으로 동기화해주는 방식입니다.
useActionState
사용// 서버에서 실행되는 비동기 함수
async function myServerAction(state) {
// 서버에서 비동기 작업을 처리 (예: 데이터베이스에 저장)
await fetch('/api/submit', { method: 'POST' });
return { ...state, submitted: true };
}
function MyComponent() {
// useActionState 훅 사용
const [state, formAction, isPending] = useActionState(myServerAction, { submitted: false });
return (
<div>
<h1>{state.submitted ? 'Form Submitted!' : 'Form Not Submitted'}</h1>
<button onClick={() => formAction(state)} disabled={isPending}>
{isPending ? 'Submitting...' : 'Submit'}
</button>
</div>
);
}
✔️ 서버 액션을 클라이언트에서 직접 호출하여 자동으로 상태 동기화가 이루어집니다.
✔️ 상태 관리와 비동기 작업 처리가 훨씬 간단해져, 복잡한 로직을 수동으로 작성할 필요가 없습니다.
✔️ 로딩 상태(isPending
)나 에러 처리 등을 useActionState
가 자동으로 관리해 주기 때문에, 클라이언트에서 별도로 로직을 작성할 필요가 없습니다.
useActionState
사용 방법useActionState
는 서버에서 실행할 비동기 함수(fn
)와 초기 상태(initialState
)를 받아 서버 액션을 클라이언트에서 실행합니다. 이 훅을 사용하면 서버 액션의 상태를 자동으로 동기화하고, 로딩 상태까지 관리할 수 있습니다.
const [state, formAction, isPending] = useActionState(fn, initialState, permalink?);
📌 파라미터
fn
: 서버에서 실행할 비동기 함수입니다. 클라이언트에서 이 함수를 호출하면 서버에서 해당 작업이 실행됩니다.initialState
: 해당 상태의 초기값을 설정합니다.permalink
(선택 사항):true
로 설정하면 상태가 URL에 포함되어 상태 공유 및 북마크가 가능합니다.
📌 반환 값
state
: 현재 상태 값입니다. 서버와 클라이언트 간의 동기화된 상태를 제공합니다.formAction
: 서버 액션을 트리거할 수 있는 함수입니다. 이 함수를 호출하여 서버에서 비동기 작업을 실행할 수 있습니다.isPending
: 서버 액션이 진행 중인지 여부를 나타내는 불리언 값입니다.
서버에서 실행될 비동기 함수를 정의하고, 이를 useActionState
에 전달하여 상태를 업데이트합니다.
async function myServerAction(state) {
// 서버에서 비동기 작업을 처리
await fetch('/api/update-data', { method: 'POST' });
return { ...state, updated: true };
}
클라이언트에서는 useActionState
를 사용하여 서버 액션을 트리거하고, 상태를 업데이트할 수 있습니다.
<button onClick={() => formAction(state)}>Update</button>
isPending
값을 사용하여 서버 액션이 진행 중인지 여부를 알 수 있으며, 이 값을 통해 로딩 UI를 표시할 수 있습니다.
{isPending && <p>Updating...</p>}
useActionState
는 클라이언트에서 발생한 상태 변경을 서버와 자동으로 동기화합니다.