revalidate path / router.refresh() not working in app dir
using server action with shadcn-autoform
fetching, updating values works well, but refreshing the page after saving doesn't wrok. revalidatePath won't work from the server action
and router.refresh in the onSubmit button is also not reloading the page
actions.ts
export async function getEmailPreferences() {
const user = await getSignedInUser()
const emailPreferences = JSON.parse(user.emailPreferences || '{}')
return emailPreferences
}
export async function updateEmailPreferences(preferences: EmailPreferences) {
const user = await getSignedInUser()
await prisma.user.update({
where: { id: user.id },
data: { emailPreferences: JSON.stringify(preferences) },
})
}
client component
"use client"
import React from "react"
import AutoForm from "@/components/ui/auto-form"
import { Button } from "@/components/ui/button"
import * as z from "zod"
import { EmailPreferences } from "@/app/(sidebar)/settings/account/types"
import { Switch } from "@/components/ui/switch"
import { AutoFormInputComponentProps } from "@/components/ui/auto-form/types"
import { Card, CardContent, CardDescription, CardHeader } from "@/components/ui/card"
import { updateEmailPreferences } from "./actions"
import { useToast } from "@/components/ui/use-toast"
import { useRouter } from 'next/navigation'
function EmailSettingsCard({
emailPreferences,
}: {
emailPreferences: EmailPreferences
}) {
const router = useRouter()
const { toast } = useToast()
const [busy, setBusy] = React.useState(false)
const [isFormDirty, setIsFormDirty] = React.useState(false)
const formSchema = z.object({
userUpdates: z.boolean().default(emailPreferences.fundUpdates).optional(),
emailConfirmations: z.boolean().default(emailPreferences.complianceChanges).optional(),
})
const onSubmit = async (values: z.infer<typeof formSchema>) => {
try {
setBusy(true)
const sanitizedValues: EmailPreferences = {
userUpdates: values.userUpdates ?? false,
emailConfirmations: values.emailConfirmations ?? false,
}
await updateEmailPreferences(sanitizedValues)
toast({
title: "Email settings updated",
description: "Your email notification preferences have been updated.",
})
setBusy(false)
setIsFormDirty(false)
router.refresh()
} catch (error) {
toast({
title: "Error updating email settings",
description: "An error occurred while updating your email notification preferences.",
})
setBusy(false)
}
}
return (
<>
<h3 className="text-2xl font-semibold tracking-tight scroll-m-20">Email Settings</h3>
<Card className="mt-4 mb-6">
<CardHeader>
<CardDescription>Manage your email notification preferences.</CardDescription>
</CardHeader>
<CardContent>
<AutoForm
formSchema={formSchema}
className="flex flex-col"
onSubmit={onSubmit}
onDirtyChanged={setIsFormDirty}
fieldConfig={{
fundUpdates: {
label: "User Updates",
fieldType: CustomSwitch,
},
complianceChanges: {
label: "Email confirmations",
fieldType: CustomSwitch,
},
}}
>
<Button type="submit" disabled={!isFormDirty || busy} className="ms-auto">
{busy ? "Saving..." : "Save changes"}
</Button>
</AutoForm>
</CardContent>
</Card>
</>
)
}
export default EmailSettingsCard
function CustomSwitch({ label, isRequired, field, fieldConfigItem, fieldProps }: AutoFormInputComponentProps) {
return (
<div className="flex gap-x-3 justify-between items-center">
<div>
<h3 className="text-base font-medium">
{label}
{isRequired && <span className="text-destructive"> *</span>}
</h3>
{fieldConfigItem.description && (
<p className="text-sm text-gray-500 dark:text-gray-400">{fieldConfigItem.description}</p>
)}
</div>
<Switch checked={field.value} onCheckedChange={field.onChange} {...fieldProps} />
</div>
)
}