Unlocking the Power of useActionState in Next.js 15: Enhancing formAction with Additional Arguments

Within my Nextjs 15 project, I have implemented a contact form as a client component. To enhance security measures, I integrated Google Captcha v3 by following the documentation provided.

Upon submitting the contact form, a submission handler is activated. This handler utilizes a function to generate a Captcha token and then triggers a server action responsible for sending an email to the website owner.

In order to improve the user experience on the frontend, I am leveraging the useActionState hook within the component. By utilizing the values of isPending and state, I can better communicate the server action's status to the user.

The structure of my component is set up as follows:

    const initialState = {
    status: 'success',
    messages: [],
    } 
    const Contact = () => {
      const [state, formAction, isPending] = useActionState(sendEmail, initialState)

      const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
      event.preventDefault()
    
      const captchaToken = await getCaptchaToken()
    
      const formData = new FormData(event.currentTarget)
      formAction(formData, captchaToken)
    }

    return (
      <div>
        <h2>
          Contact
        </h2>
        <form onSubmit={handleSubmit}>
         <label>
          Name
          <input
            required
            type='text'
            name='fname'
            placeholder='enter your first name'
          />
         </label>

         <label>
          Email
          <input
            required
            type='email'
            name='email'
            placeholder='enter your email'/>
         </label>

         <button>
          {isPending ? 'Pending' : 'Submit'}
         </button>
         {state.messages.length > 0 &&
          state.messages.map((message, index) => {
            return (
              <p
                key={index}
              >
                {message}
              </p>
            )
          })}
      </form>
    </div>
  )
}

    

The server action implementation is as follows:

        export async function sendEmail(
          prevState: { messages: string[] },
          formData: FormData,
          captchaToken: string
        ) {
         // Implement necessary logic using the token and formData
         return {
          status: 'success',
          messages: ['Thank you for contacting us!']
         }
      }

An issue arises with TypeScript in relation to handling formAction within the handleSubmit function. Specifically, the error message states: "Expected 0 arguments, but got 2".

To resolve this issue while still passing the captchaToken to the formAction function alongside the formData, how can I ensure that it is properly received by sendEmail?

Answer №1

To achieve this, we can utilize the bind method.

Begin by updating your useActionState hook as shown below:

const sendEmailWithCaptchaToken = sendEmail.bind(null, {
    captchaToken: "abc123456def",
})

const [state, formAction, isPending] = useActionState(sendEmailWithCaptchaToken, initialState)

Next, modify your server action to include the following changes:

export async function sendEmail(
    extras: { captchaToken: string },
    prevState: { messages: string[] },
    formData: FormData,
) {
    console.log("extras", extras)
    //...
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips for setting default values for named parameters in JavaScript

In my TypeScript method, I am using named parameters like this public foo({x, y, z , m , n} : {x:string, y: number, z: number, m?:string, n?:number}) { } The parameters m and n will be provided from another object like const defaults = { m : 'M&apo ...

What is the significance of the KnownKeys type within IndexedDB?

type FilteredKeys<T> = { [K in keyof T]: string extends K ? never : number extends K ? never : K; } extends { [_ in keyof T]: infer U } ? U : never; This type is quite puzzling to me. I find it difficult to grasp its purpose. It appears to fil ...

After a period of inactivity, the Angular observable object fails to trigger

I have developed a method to create an observable by designing a class that maintains the object and class observable's next() whenever there is an assignment. class myObsClass{ private sub; public obj; public obj$; constructor(){ this.sub = new ...

Avoid stopping Bootstrap Vue's events

Need help with a b-form-select control in Bootstrap Vue. Trying to execute a function when the value changes, but want the option to cancel the event and keep the original value. Complicating matters, the select is in a child component while the function ...

Got a value of `false` for an attribute `closable` that is not meant to be a

Here's the code snippet I have: import { Modal } from "antd"; import styled from "styled-components"; export const StANTModal = styled(Modal)` & .ant-modal-content { border-radius: 20px; overflow: hidden; } `; And ...

Getting a "function is not defined" error in Angular 6 while using it within a nested function

I'm facing an issue related to typescript, where the following code is causing trouble: private loadTeams = function(){ let token = sessionStorage.getItem('token'); if(token !== undefined && token !== null && token ...

Having an issue in Angular 2 where the correct function is not triggered when a button is placed within a selectable anchor

Within an anchor element, I have a button that triggers its own click listener for an editing popup module. The anchor itself has another click listener assigned to it. For example: <a (click)="onClick(myId)" class="list-group-item clearfix"> < ...

Struggling to display blob URL on "pdf-viewer" component with "ng2-pdf-viewer" in Angular version 10

I am facing an issue with an API that returns uploaded files as blobs. When trying to bind the src with a blob URL, nothing is shown. However, if I bind it with a direct URL, the PDF file is displayed successfully. Below is my code snippet. My TypeScript ...

Using TypeScript with Mongoose: Issue with finding documents conditionally on model results in error: Union type signatures are not compatible

Seeking assistance on how to conditionally access a mongoose model in TypeScript code. Does anyone have a solution to resolve this TypeScript error? Each member of the union type has signatures, but none of those signatures are compatible with each other ...

Leverage a TypeScript property descriptor to substitute the accessors without compromising on composability

Is there a way to create a TypeScript property descriptor that can override accessors and still be easily composed with other functionality? ...

Error with importing images detected on the React/Next.js website

Recently, I encountered a frustrating bug in my React/Next JS site related to displaying images. I'm unable to show any image when using src='/static/images/service'. Even importing and assigning the route like this: import Image1 from "../ ...

Discovering updates to a read-only input's [ngModel] binding in an Angular 2 directive

One issue I'm facing is with a directive that sets the height of a textarea dynamically based on its content: @Directive({ selector: '[fluidHeight]', host: { '(ngModelChange)': 'setHeight()' } }) export class ...

Is there a way to identify when Change Detection has been triggered in Angular2 without using @Output directly?

Imagine the following structure of components in Angular2 A B D E When D triggers an event by clicking on B, Angular2 will automatically initiate change detection starting from the root component A. But is there a method to log this change detect ...

Find the identifier that does not currently exist in the collection of objects

There is a situation where I have an array and an object that consists of arrays of ids, which are essentially permission objects. My goal now is to extract the ids that do not exist in the given object. Can someone assist me with devising the necessary l ...

The email sending functionality of NextJS API is experiencing difficulties when deployed on AWS Amplify platform

I am currently working on a NextJS project where I have implemented an API route in Next to send emails using Gmail's STMP. Everything was working perfectly fine on my localhost environment, but when I deployed it on AWS Amplify, I started encounterin ...

Angular has got us covered with its latest feature - combining Async Await with an EventListener

I have been facing this issue for the past day and need help creating a specific scenario: <img [src]="userdp | async" /> In my component.ts file, I want to include only this line: this.userdp = this._userService.getUserDp(); Here is the ...

Obtain access to global.window.localStorage within getServerSideProps

I have a component that receives props with data and renders the data. In my functionality within the getServerSideProps, I am attempting to retrieve data from localStorage. However, due to window being undefined, I am unable to do so. I have tried using ...

Guide on creating a similar encryption function in Node JS that is equivalent to the one written in Java

In Java, there is a function used for encryption. public static String encryptionFunction(String fieldValue, String pemFileLocation) { try { // Read key from file String strKeyPEM = ""; BufferedReader br = new Buffer ...

A specialized type that guarantees a string union includes a particular string literal

I need to define a Mapped type that specifies a field named status which can be either a string or the string value ready: This example works as expected: export type ValidServiceState = HasReady<{ status: "ready" }>; The following should ...

The configuration object is invalid. Angular has initialized Webpack using a configuration object that does not align with the API schema

When attempting to run the angular application with "ng serve -o", I encountered an error message stating "Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema." Prior to this issue, "n ...