IdoPesok / zsa

https://zsa.vercel.app
MIT License
447 stars 13 forks source link

revalidatePath in server actions causes nothing to happen on success #97

Closed drewhamlett closed 4 weeks ago

drewhamlett commented 1 month ago

This worked before I upgraded today. Might be related to https://github.com/IdoPesok/zsa/pull/91 ?

"zsa": "^0.3.2", "zsa-react": "^0.1.4"

    // Server action
    revalidatePath(`/admin/shop/categories/${categoryId}`)

    return {
      message: 'Item added',
    }
  const onClick = async () => {
    console.debug('Fired')
    const [, err] = await execute({
      catalogItemId: Number(item.objectID),
      categoryId,
    })

    console.debug('This works if err')
    console.debug('err', err)

    if (err) {
      toast({
        title: 'Error',
        description: 'Error adding item',
      })
      return
    }

    console.log('Never called if revalidatePath is hit')

    toast({
      title: 'Item added ✅',
      description: 'Item added!',
    })
  }
Screen Shot 2024-06-06 at 10 51 06 AM
IdoPesok commented 1 month ago

Hi, happy to help. Yes, this is probably related to #91. TLDR, is the resolve of the promise now gets fired once the transition finishes. On prev versions it was weird because it would run your on success however the status would still be pending because revalidatePath or redirect were still running. On the latest versions that you mentioned this is fixed.

I started investigating this but still not able to replicate it. Here is some code I am working with

import IncrementExample from "@/content/docs/examples/introduction/increment-example"

export default async function RevalidatePage() {
  // sleep for 5 seconds
  await new Promise((resolve) => setTimeout(resolve, 5000))
  const randomNumber = Math.floor(Math.random() * 10000)
  return (
    <div>
      <h1>Revalidate Page</h1>
      <p>Random number: {randomNumber}</p>
      <IncrementExample />
    </div>
  )
}
"use client"

import { Button } from "@/components/ui/button"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { useState } from "react"
import { toast } from "sonner"
import { useServerAction } from "zsa-react"
import { incrementNumberAction } from "./actions"

export default function IncrementExample() {
  const [counter, setCounter] = useState(0)

  const { isPending, execute, data, error, isError } = useServerAction(
    incrementNumberAction
  )

  return (
    <Card className="not-prose">
      <CardHeader>
        <CardTitle>Increment Number</CardTitle>
      </CardHeader>
      <CardContent className="flex flex-col gap-4">
        <Button
          disabled={isPending}
          onClick={async () => {
            const [data, err] = await execute({
              number: counter,
            })

            if (err) {
              return
            }

            toast("got data" + data)
            setCounter(data)
          }}
        >
          Invoke action
        </Button>
        <p>Count:</p>
        <div>{isPending ? "saving..." : data}</div>
      </CardContent>
    </Card>
  )
}
"use server"

import { revalidatePath } from "next/cache"
import z from "zod"
import { createServerAction } from "zsa"

export const incrementNumberAction = createServerAction()
  .input(
    z.object({
      number: z.number(),
    })
  )
  .handler(async ({ input }) => {
    await new Promise((resolve) => setTimeout(resolve, 500))

    revalidatePath("/revalidate", "page")

    return input.number + 2
  })

Here is a video of the toast showing:

https://github.com/IdoPesok/zsa/assets/43461847/1dbe771f-e9df-4af3-86bf-e3766ba2d906

Are you possibly doing a redirect and a revalidatePath? Going to keep trying to replicate it. Will update when I have it going.

IdoPesok commented 1 month ago

@drewhamlett do you show the isPending state in your UI? I'm curious if the code gets stuck on isPending. The toast should show right after status goes from "pending" -> "success"

IdoPesok commented 4 weeks ago

Hi, wanted to check back in and report an update in the latest version of zsa-react@0.1.5. You can now use useServerAction alongside

using the new function executeFormAction

Here are the docs

I think this was the issue based on what I have tested. If it is still not working, happy to reopen this. Closing for now.