Next.js Discord

Discord Forum

useFormState: No overload matches this call

Answered
Plott Hound posted this in #help-forum
Open in Discord
Plott HoundOP
const [state, formAction] = useFormState(handleDeleteTask, initialState)

No overload matches this call.
  Overload 1 of 2, '(action: (state: { message: string; }) => { message: string; } | Promise<{ message: string; }>, initialState: { message: string; }, permalink?: string | undefined): [state: { message: string; }, dispatch: () => void]', gave the following error.
    Argument of type '(prevState: any, formData: FormData) => Promise<{ message: string; }>' is not assignable to parameter of type '(state: { message: string; }) => { message: string; } | Promise<{ message: string; }>'.
      Target signature provides too few arguments. Expected 2 or more, but got 1.
  Overload 2 of 2, '(action: (state: { message: string; }, payload: FormData) => { message: string; } | Promise<{ message: string; }>, initialState: { message: string; }, permalink?: string | undefined): [state: ...]', gave the following error.
    Argument of type '{ message: null; }' is not assignable to parameter of type '{ message: string; }'.
      Types of property 'message' are incompatible.
        Type 'null' is not assignable to type 'string'.ts(2769)
(alias) useFormState<{
    message: string;
}>(action: (state: {
    message: string;
}) => {
    message: string;
} | Promise<{
    message: string;
}>, initialState: {
    message: string;
}, permalink?: string | undefined): [state: ...] (+1 overload)
import useFormState
Answered by Plott Hound
I think it might be as simple as changing:

const initialState = {
  message: null,
}

to
const initialState = {
  message: "",
}
View full answer

3 Replies

Plott HoundOP
Delete task form:
'use client'

import { useFormState, useFormStatus } from "react-dom";
import { handleDeleteTask} from "@/actions/TaskActions";
import { IconTrash } from "@tabler/icons-react";

const initialState = {
  message: null,
}

function DeleteButton() {
  const { pending } = useFormStatus()

  return (
    <button 
      type="submit" 
      aria-disabled={pending}
      className="p-1 bg-red-500 text-white rounded"
    >
      <IconTrash size={16} />
    </button>
  )
}

export default function DeleteTaskForm({ boardId, taskId, taskName }: { boardId: string; taskId: string; taskName: string; }) {
  const [state, formAction] = useFormState(handleDeleteTask, initialState)

  return (
    <form action={formAction}>
      <input type="hidden" name="boardId" value={boardId} />
      <input type="hidden" name="taskId" value={taskId} />
      <input type="hidden" name="taskName" value={taskName} />
      <DeleteButton />
      <p aria-live="polite" className="sr-only" role="status">
        {state?.message}
      </p>
    </form>
  )
}
action:
'use server';
import { z } from 'zod'
import prisma from '@/db/prisma';
import { revalidatePath } from 'next/cache'

export async function handleDeleteTask(prevState: any, formData: FormData) {

    const DeleteTaskSchema = z.object({
        taskId: z.string().min(1),
        taskName: z.string().min(1),
    });

    const data = DeleteTaskSchema.parse({
        taskId: formData.get('taskId') as string,
        taskName: formData.get('taskName') as string,
    })

    try {

        await prisma.task.delete({
            where: {
                id: data.taskId,
            }
        });
        
        const boardId = formData.get('boardId') as string;
        revalidatePath(`/board/${boardId}`);
        return { message: `Deleted todo ${data.taskName}` }
    } catch (e) {
        return { message: 'Failed to delete task' }
    }
    
}
Plott HoundOP
I think it might be as simple as changing:

const initialState = {
  message: null,
}

to
const initialState = {
  message: "",
}
Answer