HJS

useActionState

1️⃣ useActionState란?

useActionState는 Next.js 13에서 도입된 서버 액션 클라이언트에서 사용할 수 있도록 도와주는 훅입니다. 이 훅은 서버에서 실행되는 비동기 작업을 클라이언트에서 쉽게 실행하고, 그 상태를 클라이언트와 서버 간에 동기화할 수 있게 해줍니다. useActionState를 사용하면 폼 상태 관리뿐만 아니라, 서버 액션을 통해 클라이언트와 서버 간의 상태를 효율적으로 동기화할 수 있습니다.




2️⃣ useActionState vs 기존 상태 관리

🔹 일반적인 React 상태 관리 (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가 자동으로 관리해 주기 때문에, 클라이언트에서 별도로 로직을 작성할 필요가 없습니다.




3️⃣ useActionState 사용 방법

1. 기본 사용법

useActionState는 서버에서 실행할 비동기 함수(fn)와 초기 상태(initialState)를 받아 서버 액션을 클라이언트에서 실행합니다. 이 훅을 사용하면 서버 액션의 상태를 자동으로 동기화하고, 로딩 상태까지 관리할 수 있습니다.

const [state, formAction, isPending] = useActionState(fn, initialState, permalink?);

📌 파라미터

📌 반환 값

2. 서버 액션 정의

서버에서 실행될 비동기 함수를 정의하고, 이를 useActionState에 전달하여 상태를 업데이트합니다.

async function myServerAction(state) {
  // 서버에서 비동기 작업을 처리
  await fetch('/api/update-data', { method: 'POST' });
  return { ...state, updated: true };
}

3. 클라이언트에서 상태 변경

클라이언트에서는 useActionState를 사용하여 서버 액션을 트리거하고, 상태를 업데이트할 수 있습니다.

<button onClick={() => formAction(state)}>Update</button>

4. 로딩 상태 처리

isPending 값을 사용하여 서버 액션이 진행 중인지 여부를 알 수 있으며, 이 값을 통해 로딩 UI를 표시할 수 있습니다.

{isPending && <p>Updating...</p>}

5. 상태 동기화

useActionState는 클라이언트에서 발생한 상태 변경을 서버와 자동으로 동기화합니다.