#useActionState is not triggering my form action

1 messages · Page 1 of 1 (latest)

hearty sphinxBOT
#

Hi @kind spoke. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

Based on the information provided in the knowledge sources, it appears that you're encountering an issue with useActionState, which is not available in the stable version of Next.js and React that you're likely using.

The useActionState hook is part of React 19, which is currently in beta. Instead, for stable versions of Next.js (14.2.3 and earlier) and React 18, you should use useFormState from react-dom.

Here's how you can modify your code to use useFormState:

import { useFormState } from 'react-dom';

export function CreateEventForm() {
  const [state, formAction] = useFormState(createEvent, undefined);

  return (
    <form action={formAction}>
      // ...
    </form>
  );
}

Your server action (createEvent) should remain the same.

This change should resolve the issue and allow your form action to be triggered correctly.

It's worth noting that the Next.js documentation has been updated to reflect this difference. As mentioned in the Next.js documentation (https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations#server-side-form-validation):

These examples use React's useFormState hook, which is bundled with the Next.js App Router. If you are using React 19, use useActionState instead.

If you want to use useActionState, you would need to upgrade to the canary versions of Next.js and React, but this is not recommended for production use unless you're prepared to deal with potential instability.

Github issue discussion (https://github.com/vercel/next.js/issues/65673) provides more context on this issue and potential workarounds.

#

Remember to always check the version compatibility when using new features or hooks in Next.js and React.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@kind spoke Kapa.ai is still learning and improving, please let me know how I did by reacting below.

kind spoke
#

@hearty sphinx But i'm using Next.js(15.0.2) which use React 19

hearty sphinxBOT
#

Let me check the knowledge base for you again. Give me one moment! :books:

#

Thank you for providing that additional information. You're correct, and I apologize for my previous assumption. Since you're using Next.js 15.0.2, which indeed uses React 19, you should be able to use useActionState.

In Next.js 15 with React 19, useActionState is the recommended hook for handling form state with server actions. Here's how you can use it correctly:

import { useActionState } from 'react';

export function CreateEventForm() {
  const [state, formAction] = useActionState(createEvent, undefined);

  return (
    <form action={formAction}>
      // ...
    </form>
  );
}

This syntax is correct and should work with Next.js 15.0.2 and React 19.

If you're still experiencing issues with the action not being triggered, there might be other factors at play. Here are a few things to check:

  1. Make sure your createEvent function is properly exported and imported.
  2. Verify that your form fields have name attributes that match the keys in your EventSchema.
  3. Check your browser console for any JavaScript errors that might be preventing the form submission.

If the issue persists, it might be helpful to add some logging or debugging statements in your createEvent function to see if it's being called at all.

Also, keep in mind that as of the latest information available in the provided knowledge sources, there have been some reported issues with useActionState in certain scenarios, particularly with the first form submission after a page refresh Github issue discussion (https://github.com/vercel/next.js/issues/66426). If you're experiencing something similar, you might want to check for any recent updates or workarounds.

#

If you continue to face problems, consider opening an issue on the Next.js GitHub repository with a minimal reproducible example, as this could potentially be a bug in the current implementation.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@kind spoke Kapa.ai is still learning and improving, please let me know how I did by reacting below.

kind spoke
#

@hearty sphinx There is an error when sending the form in date, image and visibility

hearty sphinxBOT
#

Let me check the knowledge base for you again. Give me one moment! :books:

#

Based on the information you've provided and the context from our previous conversation, it seems you're encountering errors with specific fields (date, image, and visibility) when submitting your form. Let's look at how we can address these issues:

  1. Date field:
    Make sure the date format you're submitting matches the format expected by your EventSchema. If you're using a date input, the format should be "YYYY-MM-DD". You might need to adjust your schema or preprocess the date before validation.

  2. Image field:
    The image field is likely expecting a file upload. Ensure that your form has the correct enctype attribute set for file uploads:

    <form action={formAction} encType="multipart/form-data">
      {/* ... */}
    </form>
    

    Also, in your server action, you may need to handle the file upload differently. The formData.get("image") will return a File object, not a string.

  3. Visibility field:
    Check that the visibility field in your form matches the expected type in your EventSchema. If it's supposed to be a boolean, make sure you're sending a boolean value, not a string.

To help debug these issues, you can add more detailed error logging in your createEvent function:

'use server';

import { EventSchema, EventFormState } from "@/app/lib/definitions";

export async function createEvent(state: EventFormState, formData: FormData) {
  const rawData = {
    title: formData.get("title"),
    description: formData.get("description"),
    date: formData.get("date"),
    time: formData.get("time"),
    image: formData.get("image"),
    visibility: formData.get("visibility"),
    price: formData.get("price"),
    minorsPrice: formData.get("minorsPrice"),
    priceReducedVisibility: formData.get("priceReducedVisibility"),
    pricePartners: formData.get("pricePartners"),
  };
#

console.log("Raw form data:", rawData);

const validatedFields = EventSchema.safeParse(rawData);

if (!validatedFields.success) {
console.error("Validation errors:", validatedFields.error.flatten().fieldErrors);
return {
errors: validatedFields.error.flatten().fieldErrors,
};
}

console.log("Validated data:", validatedFields.data);
// ... rest of your function
}


This will help you see exactly what data is being received from the form and where the validation is failing.

If you're still encountering issues, it might be helpful to review your `EventSchema` definition to ensure it matches the expected types for each field, especially for date, image, and visibility.

Remember, when using `useActionState` with Next.js 15 and React 19, you should be able to access the form state and any returned errors in your component:

```tsx
const [state, formAction] = useActionState(createEvent, undefined);

// ... in your JSX
{state?.errors?.date && <p>Error with date: {state.errors.date}</p>}
{state?.errors?.image && <p>Error with image: {state.errors.image}</p>}
{state?.errors?.visibility && <p>Error with visibility: {state.errors.visibility}</p>}

This will help you display specific error messages for each problematic field.

If these suggestions don't resolve your issue, you might want to check the Next.js documentation on form validation (https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations#server-side-validation-and-error-handling) for any updates or additional information that might be relevant to your specific case.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@kind spoke Kapa.ai is still learning and improving, please let me know how I did by reacting below.

kind spoke
#

@hearty sphinx The visibility is sending as a string

hearty sphinxBOT
#

Let me check the knowledge base for you again. Give me one moment! :books:

#

Based on the information you've provided, it seems the visibility field in your form is being sent as a string instead of the expected type (which is likely a boolean or an enum).

This is a common issue with form submissions, as HTML form inputs typically send all values as strings. To resolve this, you have a couple of options:

  1. Modify your EventSchema to expect a string for visibility, then convert it to the desired type after validation.

  2. Convert the visibility value to the correct type before validation in your server action.

Here's how you can modify your createEvent function to handle this:

'use server';

import { EventSchema, EventFormState } from "@/app/lib/definitions";

export async function createEvent(state: EventFormState, formData: FormData) {
  const rawData = {
    // ... other fields
    visibility: formData.get("visibility") === 'true', // Convert to boolean
    // ... other fields
  };

  console.log("Raw form data:", rawData);

  const validatedFields = EventSchema.safeParse(rawData);

  // ... rest of your function
}

In this example, we're converting the visibility value to a boolean before passing it to the schema validation. Adjust the conversion logic based on what values you're expecting from your form.

If visibility is supposed to be an enum or a specific set of string values, you might want to validate it explicitly:

const visibilityOptions = ['public', 'private', 'friends']; // adjust based on your needs
const visibility = formData.get("visibility");
if (typeof visibility === 'string' && visibilityOptions.includes(visibility)) {
  rawData.visibility = visibility;
} else {
  // Handle invalid visibility value
  console.error("Invalid visibility value:", visibility);
  return {
    errors: { visibility: ["Invalid visibility option"] },
  };
}
#

Remember to update your EventSchema to match the expected types after these changes.

If you're using a select input for visibility in your form, make sure the value attributes of your options match the expected values:

<select name="visibility">
  <option value="public">Public</option>
  <option value="private">Private</option>
  <option value="friends">Friends Only</option>
</select>

By making these adjustments, you should be able to correctly handle the visibility field in your form submission and validation process.

Next.js documentation on server-side validation (https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations#server-side-validation-and-error-handling) provides more information on handling form data and validation in server actions.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@kind spoke Kapa.ai is still learning and improving, please let me know how I did by reacting below.

kind spoke
#

@hearty sphinx In image say "Input not instance of file"

My schema for the image:

image: z
    .instanceof(File)
    .refine((file) => file.size > 0, { message: "La imatge és necessària" })
    .refine((file) => file.size === 0 || file.type.startsWith("image/"), {
      message: "El fitxer ha de ser una imatge.",
    })
    .refine((file) => file.size < 4000000, {
      message: "Image must less than 4MB",
    }),
hearty sphinxBOT
#

Let me check the knowledge base for you again. Give me one moment! :books:

#

Based on the error message "Input not instance of file" and the schema you've provided for the image field, it seems that the issue is related to how the file is being handled in your server action. Let's address this problem step by step.

  1. First, it's important to note that when using formData.get("image") in a server action, it doesn't return a File object directly. Instead, it returns a File-like object that doesn't pass the instanceof File check.

  2. To resolve this, you need to modify your server action to properly handle the file upload. Here's how you can adjust your createEvent function:

'use server';

import { EventSchema, EventFormState } from "@/app/lib/definitions";

export async function createEvent(state: EventFormState, formData: FormData) {
  const imageFile = formData.get("image");
  
  // Check if imageFile is a File-like object
  const isFileObject = imageFile && typeof imageFile === 'object' && 'name' in imageFile && 'size' in imageFile && 'type' in imageFile;

  const rawData = {
    // ... other fields
    image: isFileObject ? imageFile : null,
    // ... other fields
  };

  console.log("Raw form data:", rawData);

  const validatedFields = EventSchema.safeParse(rawData);

  // ... rest of your function
}
  1. You might also need to adjust your EventSchema to handle this File-like object. Instead of using z.instanceof(File), you can create a custom validation:
import { z } from 'zod';

const FileSchema = z.object({
  name: z.string(),
  size: z.number(),
  type: z.string(),
}).refine((file) => file.size > 0, { message: "La imatge és necessària" })
  .refine((file) => file.size === 0 || file.type.startsWith("image/"), {
    message: "El fitxer ha de ser una imatge.",
  })
  .refine((file) => file.size < 4000000, {
    message: "Image must less than 4MB",
  });
#

// In your EventSchema
image: FileSchema.nullable(),


4. Make sure your form has the correct `encType` attribute:

```tsx
<form action={formAction} encType="multipart/form-data">
  {/* ... */}
</form>
  1. If you're using useActionState, you can handle the file upload like this:
const [state, formAction] = useActionState(createEvent, undefined);

// In your JSX
<input type="file" name="image" accept="image/*" />

These adjustments should help resolve the "Input not instance of file" error and allow your form to properly handle file uploads.

Remember, when working with file uploads in Next.js, especially with server actions, you might want to consider using a more robust solution for file handling, such as Vercel Blob (https://vercel.com/docs/storage/vercel-blob/server-upload#upload-a-file-using-server-actions) for persistent file storage, as mentioned in the Next.js documentation on static assets (https://nextjs.org/docs/app/building-your-application/optimizing/static-assets).

If you continue to face issues, you might want to check the Next.js GitHub issues (https://github.com/vercel/next.js/issues) for any known problems with file uploads in the latest version, or consider opening a new issue with a minimal reproducible example.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@kind spoke Kapa.ai is still learning and improving, please let me know how I did by reacting below.

kind spoke
#

@hearty sphinx I don’t like that solution

hearty sphinxBOT
#

Let me check the knowledge base for you again. Give me one moment! :books:

#

I understand that you don't like the solution I proposed. I apologize for not meeting your expectations. Since you're using Next.js 15.0.2 with React 19, which are newer versions, there might be more up-to-date or efficient ways to handle file uploads that I'm not aware of based on the information in the knowledge sources provided.

Given that you're not satisfied with the previous suggestion, it would be helpful if you could provide more specific details about what aspects of the solution you don't like or what particular requirements you have for handling file uploads. This would allow me to better understand your needs and potentially offer a more suitable alternative.

If you have a particular approach in mind or if there are specific constraints or preferences you're working with, please share those. This will help me provide a more tailored response that aligns with your project's needs and your preferred development style.

In the meantime, you might want to check the latest Next.js documentation (https://nextjs.org/docs) for any recent updates or best practices regarding file uploads with server actions, as the framework is rapidly evolving and new features or recommended patterns might have been introduced.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: