Next.js Discord

Discord Forum

Server action not being called

Answered
Noronha posted this in #help-forum
Open in Discord
  const onSubmit = async (formData: FormData) => {
    const files = formData.getAll('file') as File[];

    if (!files || files?.length === 0 || files[0].size === 0) {
      return;
    }

    console.log('Did I get here?');
    console.log(uploadFiles);

    const response = await uploadFiles(files);

    console.log('got response >>');
    console.log(response);


Got this response:
uploader-modal.tsx:46 Did I get here?
uploader-modal.tsx:47 Æ’ () {
    // $FlowFixMe[method-unbinding]
    var args = Array.prototype.slice.call(arguments);
    return callServer(id, args);
  }
react-dom.development.js:8597 Uncaught undefined
6redirect-boundary.js:57 Uncaught undefined
not-found-boundary.js:37 Uncaught undefined


This is the server action:

'use server';

import { FormResponse } from '@/types';
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';

// ...
export async function uploadFiles(
  files: File[],
): Promise<FormResponse<string[]>> {
  console.log('uploading files');
  console.log(files);
  console.log('------------------------------------------------');

  try {
    const response = await Promise.all(
      files.map(async (file) => {
        console.log('processing....');
        console.log(file);

        const Body = (await file.arrayBuffer()) as Buffer;
        const Key = `${new Date().toISOString()}-${file.name}`;

        const params = {
          Bucket,
          Key,
          Body,
          ContentType: file.type,
        };

        console.log('params', params);
        const command = new PutObjectCommand(params);
        s3.send(command);
        return `https://${Bucket}.s3.amazonaws.com/${Key}`;
      }),
    );

    return {
      type: 'success',
      message: 'Arquivos enviados com sucesso!',
      data: response,
    };
  } catch (error) {
    return { type: 'error', message: 'Erro ao enviar arquivos' };
  }
}


Nothing was printed on server-side.
Any ideas?
Answered by Gharial
I wonder if it comes down to the serialization of the file, and how that's passed. That could explain why passing FormData directly works, since FormData is designed to handle file uploads and other form data in a way that can be properly interpreted. But when you attempted to pass File[] directly, the serialization process could've stripped away some essential information
View full answer

7 Replies

Gharial
Just a guess since I'm not at my computer - are you sure uploadFiles is being correctly called client side?
Yes @Gharial it's on a client component with useState, useRef and other client-side-only functions.
I just noticed that if we pass the formData on the server action it works, something like this:

export async function uploadFiles(
  formData: FormData,
): Promise<FormResponse<string[]>> {
  const files = formData.getAll('file') as File[];

  if (!files || files.length === 0 || files[0].size === 0) {
    return { type: 'error', message: 'Envie arquivos =]' };
  }


For me this solution in fine, but I would like to understand why it didnt work in the previous case. I have other examples were I use server actions and a client-side validation function... I'm lost 😦 @Gharial any ideas?
This also works:

  const submitFn = async (formData: FormData) => {
    const response = await uploadFiles(formData);
    console.log(response);
  };
Gharial
I wonder if it comes down to the serialization of the file, and how that's passed. That could explain why passing FormData directly works, since FormData is designed to handle file uploads and other form data in a way that can be properly interpreted. But when you attempted to pass File[] directly, the serialization process could've stripped away some essential information
Answer
Just to add onto what @Gharial said, here is the list of serializable arguments for server actions:
https://react.dev/reference/react/use-server#serializable-parameters-and-return-values
Yeah, that makes total sense. Thank you @Gharial and @jason