NextJS 13 app router doesn't refresh data on update with router.push
Unanswered
Asiatic Lion posted this in #help-forum
Asiatic LionOP
I have NextJS 13 app with app router. Which displays a table (shadcn UI) data-table with server side pagination. I have a create button that goes to a create page, And I can create a new entry into the table. On success of the API I do a
that goes back to the table page. This shows a new entry in my table. But when I do the same after going to an edit page and update an existing row and do a router push the data doesn't get updated.
router.push("/path")that goes back to the table page. This shows a new entry in my table. But when I do the same after going to an edit page and update an existing row and do a router push the data doesn't get updated.
5 Replies
Asiatic LionOP
Edit Page
import EditBrandForm from "@/components/brand/edit-brand-form";
import { DashboardHeader } from "@/components/header";
import { BASE_API_URL } from "@/constants/constants";
import { BRANDS_ENDPOINT } from "@/constants/routes";
import { getAccessTokenCookie } from "@/lib/session";
import { Brand } from "@/types/brand";
import { Metadata } from "next";
export const metadata: Metadata = {
title: "Edit brand",
};
export default async function EditBrand({
params,
}: {
params: { id: number };
}) {
const apiResponse = await fetch(
`${BASE_API_URL}${BRANDS_ENDPOINT}${params.id}`,
{
method: "GET",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${getAccessTokenCookie()}`,
},
}
);
const brandResponse: Brand = await apiResponse.json();
return (
<div>
<DashboardHeader heading="Edit brand"></DashboardHeader>
<EditBrandForm brand={brandResponse} />
</div>
);
}EditBrandForm
"use client";
type FormData = z.infer<typeof brandFormSchema>;
interface EditBrandFormProps {
brand: Brand;
}
export default function EditBrandForm({ brand }: EditBrandFormProps) {
const [isLoading, setIsLoading] = React.useState<boolean>(false);
const router = useRouter();
const { toast } = useToast();
const defaultValues: FormData = {
name: brand.name,
website: brand.website,
};
const {
register,
handleSubmit,
formState: { errors },
clearErrors,
} = useForm<FormData>({
resolver: zodResolver(brandFormSchema),
defaultValues,
});
async function onSubmit(data: FormData) {
setIsLoading(true);
const apiResponse = await brandService.editBrand(
brand.id,
data.name,
data.website
);
setIsLoading(false);
if (!apiResponse.error) {
router.push("/brands");
} else {
toast({
variant: "destructive",
title: "An unexpected error occured.",
});
}
}
return (
<form
onSubmit={handleSubmit(onSubmit)}
className="px-2 py-8 flex w-full flex-col space-y-6 sm:w-[350px]"
>
<div className="grid w-full max-w-sm items-center gap-1.5">
<Input
{...register("name")}
type="text"
placeholder="Brand name"
onChange={() => {
clearErrors("name");
}}
/>
{errors?.name && (
<p className="px-1 text-xs text-red-600">{errors.name.message}</p>
)}
</div>
<Input type="text" placeholder="Brand website" {...register("website")} />
<Button disabled={isLoading} className="w-1/2">
{isLoading && <Icons.spinner className="mr-2 h-4 w-4 animate-spin" />}
Update
</Button>
</form>
);
}Data table Page
import { BASE_API_URL } from "@/constants/constants";
import { BrandsTableShell } from "@/components/brands-table-shell";
import CreateButton from "@/components/create-button";
import { DashboardHeader } from "@/components/header";
import { getAccessTokenCookie } from "@/lib/session";
import { Metadata } from "next";
import { BRANDS_ENDPOINT } from "@/constants/routes";
export const metadata: Metadata = {
title: "Brands",
description: "Brands",
};
interface IndexPageProps {
searchParams: {
[key: string]: string | string[] | undefined;
};
}
export default async function DashboardPage({ searchParams }: IndexPageProps) {
const { page, per_page } = searchParams;
// Number of items per page
const pageSize = typeof per_page === "string" ? parseInt(per_page) : 10;
// Current page number
const pageNumber = page === undefined ? 1 : page;
const apiResponse = await fetch(
`${BASE_API_URL}${BRANDS_ENDPOINT}?page=${pageNumber}&size=${pageSize}`,
{
method: "GET",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${getAccessTokenCookie()}`,
},
}
);
const brands = await apiResponse.json();
const pageCount = brands.total_pages;
return (
<div>
<DashboardHeader heading="Brands" text="Create and manage brands">
<CreateButton text="Add brand" route="brands/create" />
</DashboardHeader>
<div className="px-2 py-10">
<BrandsTableShell data={brands.results} pageCount={pageCount} />
</div>
</div>
);
}@Asiatic Lion I have NextJS 13 app with app router. Which displays a table (shadcn UI) data-table with server side pagination. I have a create button that goes to a create page, And I can create a new entry into the table. On success of the API I do a
router.push("/path")
that goes back to the table page. This shows a new entry in my table. But when I do the same after going to an edit page and update an existing row and do a router push the data doesn't get updated.
that's due to the router cache, there is a discussion on it [here](https://github.com/vercel/next.js/discussions/54075); but basically you can run
router.refresh() after router.push() to get the updated data, or use something like window.location.href = "https://google.com"@joulev that's due to the router cache, there is a discussion on it [here](<https://github.com/vercel/next.js/discussions/54075>); but basically you can run `router.refresh()` after `router.push()` to get the updated data, or use something like `window.location.href = "https://google.com"`
Asiatic LionOP
Hi!
Thanks for pointing me to that. Tried searching on this server didn't get that. Will read that.
Thanks for pointing me to that. Tried searching on this server didn't get that. Will read that.