eddev
Snippets

Submitting Forms To RPC

Create a serverless mutation and call it from React

Use this when the frontend needs to submit to a third-party API or perform server-side work without exposing credentials in the browser.

For the full API reference, see RPC Functions. For generated GraphQL mutations, see Mutation Hooks.

Create A Mutation Route

import { rpc } from "eddev/server"
import { z } from "zod"

export default rpc.router({
  signup: rpc.procedure
    .input(
      z.object({
        email: z.string().email(),
        lists: z.array(
          z.object({
            listId: z.string(),
            title: z.string(),
          }),
        ),
      }),
    )
    .mutation(async ({ input }) => {
      const results = await Promise.all(
        input.lists.map(async (list) => {
          const params = new URLSearchParams()
          params.append("EMAIL", input.email)
          params.append("id", list.listId)

          const response = await fetch(`https://example.com/subscribe?${params}`, {
            method: "GET",
          })

          return response.ok
        }),
      )

      if (results.every((ok) => !ok)) {
        throw new Error("Failed to subscribe")
      }

      return { success: true }
    }),
})

Call It From React

import { useRPCMutation } from "eddev/hooks"
import { useState } from "react"

export function NewsletterForm() {
  const [email, setEmail] = useState("")
  const signup = useRPCMutation("api.newsletter.signup")

  if (signup.isSuccess) {
    return <p>Thank you for signing up.</p>
  }

  return (
    <form
      onSubmit={(event) => {
        event.preventDefault()
        signup.mutate({
          email,
          lists: [{ listId: "abc123", title: "Newsletter" }],
        })
      }}
    >
      {signup.isError && <p>{signup.error.message}</p>}
      <input
        type="email"
        value={email}
        disabled={signup.isPending}
        onChange={(event) => setEmail(event.currentTarget.value)}
      />
      <button type="submit" disabled={signup.isPending}>
        Sign up
      </button>
    </form>
  )
}

RPC routes are part of the serverless frontend. Make sure serverless.endpoints is configured for WordPress-hosted SPA/admin usage. See Serverless for deployment setup.

On this page