skip to Main Content

In my Next.js module, I have a form declared as follows:

<form onSubmit = {() => {
async() => await getCertificate(id)
.then(async resp => await resp.json())
.then(data => console.log(data))
.catch(err => console.error(err))
console.log("getCertificate completed")
}}>

Function getCertificate() is defined in the same .tsx file as:

async function getCertificate(id: string) : Promise<Response> {
  console.log("in getCertificate")
  const resp = await fetch(`${serverUri}/certs/${id}`)
  console.log(`Response data: ${await resp.json()}`)
  return resp
}

It appears that getCertificate() is not getting called at all. While the final console.log("getCertificate completed") inside my onSubmit handler is executing correctly, none of the console.log() statements insisde getCertificate() are being executed.

No errors are being thrown or logged to the console. The only thing appearing in the console (in addition to getCertificate completed), is Navigated to http://localhost:3000/?certId=my_cert_id.

Any idea why it is behaving like this?

(The only other things to note are that my .tsx file is decorated with 'use client' since I am utilizing a client library for certain other functionalities, and that my form definition is inside the return statement of an export default function. Everything else works as expected except for getCertificates() not being hit).

2

Answers


  1. Possible solution

    If the only problem is to get getCertificate executed, then you may try to do something like this:

    import React, { useState } from "react";
    
    const serverUri = "http://myserver.com";
    
    export default function Certificate() {
      const [id, setId] = useState("");
      async function getCertificate(id: string): Promise<Response> {
        console.log("in getCertificate");
        const resp = await fetch(`${serverUri}/certs/${id}`);
        console.log(`Response data: ${await resp.json()}`);
        return resp;
      }
      return (
        <form onSubmit={async (event: any) => {
          event.preventDefault();
          try {
            const response = await getCertificate(id);
            const data = await response.json();
            console.log(data);
          } catch (err) {
            console.error(err);
          }
          console.log("getCertificate completed");
        }}>
          <label>
            Certificate ID:
            <input type="text" value={id} onChange={e => setId(e.target.value)} />
          </label>
          <button type="submit">Submit</button>
        </form>
      );
    }
    

    execution result

    As you can see on screenshot, in getCertificate is printed to console.

    The reason why it fails to execute

    Let’s looks closer at the original function:

    () => {
        async() => await getCertificate(id)
        .then(async resp => await resp.json())
        .then(data => console.log(data))
        .catch(err => console.error(err))
        console.log("getCertificate completed")
    }
    

    As you may see here, you just define an anonymous async arrow function here (without assignment of that function to any variable, thus this function is never called) and then just execute console.log. So the console.log is the only thing that is actually executed.

    Also, you add await before call to getCertificate, it is not required and may lead to additional confusion.

    Let’s simplify this code line

    async() => await getCertificate(id)
    .then(async resp => await resp.json())
    .then(data => console.log(data))
    .catch(err => console.error(err))
    

    So first we will reformat the code to see the structure:

    async() => { 
        await getCertificate(id)
            .then(async resp => await resp.json())
            .then(data => console.log(data))
            .catch(err => console.error(err))
    }
    

    Then we remove unnecessary function definition:

    await getCertificate(id)
        .then(async resp => await resp.json())
        .then(data => console.log(data))
        .catch(err => console.error(err))
    

    Then we will remove unnecessary await:

    getCertificate(id)
        .then(async resp => await resp.json())
        .then(data => console.log(data))
        .catch(err => console.error(err))
    

    Another solution

    So using transformations in previous section we can get another way to define the whole function.

    (event: any) => {
        event.preventDefault();
        getCertificate(id)
            .then(async resp => await resp.json())
            .then(data => console.log(data))
            .then(() => console.log("getCertificate completed with no errors"))
            .catch(err => console.error(err))
            .then(() => console.log("getCertificate completed with errors"))
    }
    

    P.S.

    Note that event.preventDefault() in both solutions will block actual transmission of form data, and will force handling everything in JS instead. It is optional and may be omitted.

    Login or Signup to reply.
  2. You wrap your getCertificate call within an anonymous function that you never actually call. From the looks of it, there is no need for that wrapper function at all, so you can just move its internal logic up a level into the onSubmit function directly, like this:

    <form onSubmit = {async () => {
        try {
            const resp = await getCertificate(id);
            const data = await resp.json();
            console.log(data);
            console.log("getCertificate completed");
        } catch (err) {
            console.error(err)
        }
    }}>
    

    or using promise chaining:

    <form onSubmit = {() => {
        getCertificate(id)
            .then(async resp => await resp.json())
            .then(data => console.log(data))
            .then(() => console.log("getCertificate completed"))
            .catch(err => console.error(err))
    }}>
    

    And I’d recommend you stick to either async/await or promise chaining rather than mixing them as mixing makes the logic a bit harder to follow. Personally, I recommend async/await.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search