Next.js Discord

Discord Forum

formData.get is not a function with useFormState

Unanswered
Matt posted this in #help-forum
Open in Discord
'use client';
export default function InternalButton({ sendTo, alreadyFriends, alreadySentRequest, hasInboundRequest }: { sendTo: string, alreadyFriends: boolean, alreadySentRequest: boolean, hasInboundRequest: boolean }) {
const { pending } = useFormStatus();

let action: any
if (alreadyFriends) {
action = null;
} else if (alreadySentRequest) {
action = unsendFriendRequestAction;
} else if (hasInboundRequest) {
action = acceptFriendRequestAction;
} else {
action = sendFriendRequestAction;
}

const [state, formAction] = useFormState(action, undefined)

useEffect(() => {
if (state === 'error') {
toast.error("Error changing friend status!")
}
}, [state])

return (
#Unknown Channel
<input type="hidden" name="sendTo" value={sendTo} readOnly />
<button
aria-disabled={pending}
formAction={formAction}
>
{pending && <LoadingSpinner />}

{alreadyFriends && 'Friends'}
{alreadySentRequest && 'Unsend Friend Request'}
{hasInboundRequest && 'Accept Friend Request'}
{(!alreadyFriends && !alreadySentRequest && !hasInboundRequest) && 'Send Friend Request'}
</button>
</>
)
}```

This used to work when I just passed the action in the button formAction, but I switched it to useFormState and now I'm getting an error in the action that formData.get is not a function. When I console log formData, it's the state. Do I have something mixed up here?

3 Replies

Palomino
I've started seeing the same - did you find a workaround?
I don't actually remember what I changed specifically to fix it but this is the working version now:

"use client";

import { useFormState, useFormStatus } from "react-dom";
import {
  acceptFriendRequestAction,
  ignoreFriendRequestAction,
  sendFriendRequestAction,
  unfriendAction,
  unsendFriendRequestAction,
} from "./actions";
import LoadingSpinner from "../utilities/LoadingSpinner";
import { useActionResponseToast } from "@/hooks/useActionResponseToast";

// TODO: this should all be one component with the parent form
export default function ClientFriendRequestButtonInternal({
  targetUser,
  alreadyFriends,
  alreadySentRequest,
  hasInboundRequest,
}: {
  targetUser: string;
  alreadyFriends: boolean;
  alreadySentRequest: boolean;
  hasInboundRequest: boolean;
}) {
  let action = sendFriendRequestAction;

  if (alreadyFriends) {
    action = unfriendAction;
  } else if (alreadySentRequest) {
    action = unsendFriendRequestAction;
  } else if (hasInboundRequest) {
    action = acceptFriendRequestAction;
  }

  const { pending } = useFormStatus();
  const [state, formAction] = useFormState(action, undefined);

  useActionResponseToast(state);

  return (
    <div className="flex gap-2 flex-wrap justify-center">
      <input type="hidden" name="targetUser" value={targetUser} readOnly />
      <button
        disabled={pending}
        formAction={formAction}
        className={`flex items-center gap-2 rounded-md ${
          alreadyFriends || alreadySentRequest ? "bg-white ring-gray-300 hover:bg-gray-50" : "text-white bg-blue-500 hover:bg-blue-600"
        } px-3 py-2 text-sm text-gray-900 shadow-sm ring-1 ring-inset `}
      >
        {alreadyFriends && "Remove Friend"}
        {alreadySentRequest && "Unsend Friend Request"}
        {hasInboundRequest && "Accept Friend Request"}
        {!alreadyFriends && !alreadySentRequest && !hasInboundRequest && "Send Friend Request"}

        {pending && <LoadingSpinner />}
      </button>

      {hasInboundRequest && <IgnoreRequestButton targetUser={targetUser} />}
    </div>
  );
}

function IgnoreRequestButton({ targetUser }: { targetUser: string }) {
  const { pending } = useFormStatus();
  const [state, formAction] = useFormState(ignoreFriendRequestAction, undefined);

  useActionResponseToast(state);

  return (
    <>
      <input type="hidden" name="targetUser" value={targetUser} readOnly />
      <button
        disabled={pending}
        formAction={formAction}
        className={`flex items-center gap-2 rounded-md bg-white ring-gray-300 hover:bg-gray-50 px-3 py-2 text-sm text-gray-900 shadow-sm ring-1 ring-inset `}
      >
        Ignore Request
        {pending && <LoadingSpinner />}
      </button>
    </>
  );
}
@Palomino
Palomino
Thanks bro - I'm thinking my issue is down to using Appwrite in my project because I can implement a form with a server action fine in a clean project