Next.js Discord

Discord Forum

issues trying to run a server function on a client component

Unanswered
Japanese jack mackerel posted this in #help-forum
Open in Discord
Japanese jack mackerelOP
im not entirely sure how to fully but concisely explain my problem. my page.tsx looks like
<main className="flex min-h-screen flex-col items-center justify-between p-24">
      <h1>D&D Stat Block Form</h1>
        <Head buttonClicked={clicked} buttonClickedCallBack={buttonClicked}/>
        <Action name="Abilities"/>
        <div onClick={handleSubmit}>Submit</div>
</main>

handle submit flips clicked and within head i have a useEffect((), [clicked])

function buttonClicked(data: any){
    let formattedData = foundryHelper(data)
    console.log(formattedData)
  }


the error im getting has to do with calling a server action in a client component, i followed the doc on using server actions and made this file
"use server"
import { internalToFoundry } from "../converter/internalToFoundry"

export async function foundryHelper(data: any){
    
    let formattedData = internalToFoundry(data)
    return JSON.stringify(formattedData)
}

however that caused an error because internalToFoundry wasnt async, however when i mark that function as async, and it returns an interface i defined i get another error that "Type Top Level is not a valid async function return type in ES5 because it does not refer to a promise compatible constructor value"

i realized that atm im acctually planning to run logic solely on the client so i marked everything as use client instead so that fixed it. but in case in the future i decide i do want the inernalToFoundry logic to be server side. how would i manage that?

11 Replies

@Japanese jack mackerel im not entirely sure how to fully but concisely explain my problem. my page.tsx looks like ts <main className="flex min-h-screen flex-col items-center justify-between p-24"> <h1>D&D Stat Block Form</h1> <Head buttonClicked={clicked} buttonClickedCallBack={buttonClicked}/> <Action name="Abilities"/> <div onClick={handleSubmit}>Submit</div> </main> handle submit flips `clicked` and within head i have a `useEffect((), [clicked])` ts function buttonClicked(data: any){ let formattedData = foundryHelper(data) console.log(formattedData) } the error im getting has to do with calling a server action in a client component, i followed the doc on using server actions and made this file ts "use server" import { internalToFoundry } from "../converter/internalToFoundry" export async function foundryHelper(data: any){ let formattedData = internalToFoundry(data) return JSON.stringify(formattedData) } however that caused an error because `internalToFoundry` wasnt async, however when i mark that function as async, and it returns an interface i defined i get another error that "Type Top Level is not a valid async function return type in ES5 because it does not refer to a promise compatible constructor value" i realized that atm im acctually planning to run logic solely on the client so i marked everything as use client instead so that fixed it. but in case in the future i decide i do want the inernalToFoundry logic to be server side. how would i manage that?
im confused as to why internalToFoundry triggered an error because it wasn't async, you should be able to run regular functions in an async context.
and about the "Type Top Level is not a valid async function return type in ES5 because it does not refer to a promise compatible constructor value" error, it's because an async function is required to have a return type of Promise<T>
async function hello(): string { // <- error
  // ...
}

async function hello2(): Promise<string> { // <- now it works
  // ...
}
@iyxan23 im confused as to why `internalToFoundry` triggered an error because it wasn't async, you should be able to run regular functions in an async context.
Japanese jack mackerelOP
the error was that server actions must be async functions, and i think if i didnt have "use server" at the top it wasnt finding the function
and okay ill save that
@iyxan23 right, perhaps you have to annotate the server action's return type to be `Promise<string>`
Japanese jack mackerelOP
that somewhat makes sense ty
👍
@Japanese jack mackerel im not entirely sure how to fully but concisely explain my problem. my page.tsx looks like ts <main className="flex min-h-screen flex-col items-center justify-between p-24"> <h1>D&D Stat Block Form</h1> <Head buttonClicked={clicked} buttonClickedCallBack={buttonClicked}/> <Action name="Abilities"/> <div onClick={handleSubmit}>Submit</div> </main> handle submit flips `clicked` and within head i have a `useEffect((), [clicked])` ts function buttonClicked(data: any){ let formattedData = foundryHelper(data) console.log(formattedData) } the error im getting has to do with calling a server action in a client component, i followed the doc on using server actions and made this file ts "use server" import { internalToFoundry } from "../converter/internalToFoundry" export async function foundryHelper(data: any){ let formattedData = internalToFoundry(data) return JSON.stringify(formattedData) } however that caused an error because `internalToFoundry` wasnt async, however when i mark that function as async, and it returns an interface i defined i get another error that "Type Top Level is not a valid async function return type in ES5 because it does not refer to a promise compatible constructor value" i realized that atm im acctually planning to run logic solely on the client so i marked everything as use client instead so that fixed it. but in case in the future i decide i do want the inernalToFoundry logic to be server side. how would i manage that?
are u trying to call a serverside function on clientside?
am i understanding it correctly
@Japanese jack mackerel