IdoPesok / zsa

https://zsa.vercel.app
MIT License
763 stars 23 forks source link

useFormState and useActionState integration #64

Closed IdoPesok closed 4 months ago

IdoPesok commented 4 months ago

In response to #63

This PR introduces createActionStateHookFrom that takes in either useActionState or useFormState and makes it super easy to use zsa actions.

"use client"

import { Button } from "@/components/ui/button"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { Input } from "@/components/ui/input"
import { useActionState } from "react"
import { createActionStateHookFrom } from "zsa-react"
import { produceNewMessage } from "./actions"

const useAction = createActionStateHookFrom(useActionState)

export default function UseActionStateExample() {
  const [{ data, error }, submitAction, isPending] =
    useAction(produceNewMessage)

  return (
    <Card className="not-prose">
      <CardHeader>
        <CardTitle>Use Form State</CardTitle>
      </CardHeader>
      <CardContent className="flex flex-col gap-4">
        <form action={submitAction} className="flex flex-col gap-4">
          <Input name="name" placeholder="Enter your name..." />
          <Button>Create message</Button>
        </form>
        {isPending ? (
          <div>loading...</div>
        ) : data ? (
          <div>{data}</div>
        ) : error ? (
          <div>error : {JSON.stringify(error)}</div>
        ) : null}
      </CardContent>
    </Card>
  )
}
vercel[bot] commented 4 months ago

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
zsa ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jun 3, 2024 1:50am
changeset-bot[bot] commented 4 months ago

🦋 Changeset detected

Latest commit: 39dad2f37204ba658fd615476c10c80e9fd0c848

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package | Name | Type | | ---- | ----- | | zsa | Minor |

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

IdoPesok commented 4 months ago

This also addresses #29

karlhorky commented 4 months ago

Thanks for this!

One small piece of feedback:

IdoPesok commented 4 months ago

new proposal, fixes #70

The change adds a type: "state" to inputs

in actions.ts:

"use server"

import z from "zod"
import { createServerAction } from "zsa"

export const produceNewMessage = createServerAction()
  .input(
    z.object({
      name: z.string().min(5),
    }),
    {
      type: "state",
    }
  )
  .handler(async ({ input }) => {
    await new Promise((resolve) => setTimeout(resolve, 500))
    return "Hello, " + input.name
  })

in client component:

"use client"

import { Button } from "@/components/ui/button"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { Input } from "@/components/ui/input"
import { useActionState } from "react"
import { produceNewMessage } from "./actions"

export default function UseActionStateExample() {
  const [[data, err], submitAction, isPending] = useActionState(
    produceNewMessage,
    [null, null] // or [initialData, null]
  )

  return (
    <Card className="not-prose">
      <CardHeader>
        <CardTitle>Use Action State</CardTitle>
      </CardHeader>
      <CardContent className="flex flex-col gap-4">
        <form action={submitAction} className="flex flex-col gap-4">
          <Input name="name" placeholder="Enter your name..." />
          <Button>Create message</Button>
        </form>
        {isPending ? (
          <div>loading...</div>
        ) : data ? (
          <div>{data}</div>
        ) : err ? (
          <div>error : {JSON.stringify(err)}</div>
        ) : null}
      </CardContent>
    </Card>
  )
}
IdoPesok commented 4 months ago

closes #63 and closes #70