Revalidate not rerendering server component
Answered
LeonN posted this in #help-forum
LeonNOP
I have this route "/teachers" with the following page:
The search view is no more than a search bar and a list. I also have a button to update one resource.
I have a form to update the resource which will call a server action.
After data mutation, the data is indeed being revalidated:
but the page.tsx, does not show the modified data unless an f5 refresh is performed.
The thing is that I have another route, "/schools", with the same logic, and the behavior here is the expected: After data mutation, the page.tsx shows the mutated data.
const TeachersPage = async () => {
const res = await getTeachersService("");
if (res.error || !res.data)
return <p className="text-error">{res.message}</p>;
return (
<SearchView<Teacher>
initialResources={res.data}
createResourceHref={routes.home.teachers.create}
resourceName="maestro"
searchService={getTeachersService}
/>
);
};
export default TeachersPage;
The search view is no more than a search bar and a list. I also have a button to update one resource.
I have a form to update the resource which will call a server action.
After data mutation, the data is indeed being revalidated:
GET /teachers/5/edit 200 in 166ms
│ GET http://devcontainer:3001/api/teachers/5 200 in 1ms (cache hit)
POST /teachers/5/edit 200 in 142ms
GET /teachers 200 in 44ms
│ GET http://devcontainer:3001/api/teachers?term=&limit=5&offset=0 200 in 7ms (cache skip)
│ │ Cache skipped reason: (cache-control: no-cache (hard refresh))
GET /teachers 200 in 37ms
│ GET http://devcontainer:3001/api/teachers?term=&limit=5&offset=0 200 in 1ms (cache hit)
but the page.tsx, does not show the modified data unless an f5 refresh is performed.
The thing is that I have another route, "/schools", with the same logic, and the behavior here is the expected: After data mutation, the page.tsx shows the mutated data.
const SchoolsPage = async () => {
const res = await getSchoolsService("");
if (res.error || !res.data)
return <p className="text-error">{res.message}</p>;
return (
<SearchView<School>
initialResources={res.data}
createResourceHref={routes.home.schools.create}
resourceName="escuela"
searchService={getSchoolsService}
/>
);
};
export default SchoolsPage;
Answered by LeonN
Deepseek solved it for me:
The issue you're describing—where the UI is not updating even though the data is being revalidated—likely stems from how the resources state is managed in your SearchView component. Specifically, the resources state is initialized with initialResources, but it doesn't automatically update when initialResources changes (e.g., after revalidation).
Here’s how you can fix this:
1. Update State When initialResources Changes
The initialResources prop is passed to the component, but the resources state is only set once when the component mounts. To ensure the state updates when initialResources changes, you can use the useEffect hook.
The issue you're describing—where the UI is not updating even though the data is being revalidated—likely stems from how the resources state is managed in your SearchView component. Specifically, the resources state is initialized with initialResources, but it doesn't automatically update when initialResources changes (e.g., after revalidation).
Here’s how you can fix this:
1. Update State When initialResources Changes
The initialResources prop is passed to the component, but the resources state is only set once when the component mounts. To ensure the state updates when initialResources changes, you can use the useEffect hook.
useEffect(() => {
setResources(initialResources);
}, [initialResources]);
3 Replies
LeonNOP
As aditional info, the page.tsx is indeed making a new fetch request.
but the react part is not rerendering the resources
{
status: 200,
error: null,
success: true,
data: [
{
id: 4,
name: 'Carlos',
lastname: 'Sánchez',
profileImageUrl: 'https://placehold.jp/150x150.png',
isActive: true
},
{
id: 5,
name: 'Luisa',
lastname: 'Martínez',
profileImageUrl: 'https://placehold.jp/150x150.png',
isActive: true
},
{
id: 1,
name: 'Juan',
lastname: 'Péreza',
profileImageUrl: 'https://placehold.jp/150x150.png',
isActive: true
},
{
id: 3,
name: 'María',
lastname: 'Rodríguez',
profileImageUrl: 'https://placehold.jp/150x150.png',
isActive: true
},
{
id: 2,
name: 'Anaa',
lastname: 'Gómez',
profileImageUrl: 'https://placehold.jp/150x150.png',
isActive: true
}
]
}
but the react part is not rerendering the resources
LeonNOP
Update: Kind of found a possible explanation. This is the code of the search view:
Adding this solved it:
It turns out that the other page using the same logic was not using the searchview, but a variation of it using of it in which theres a page between the edit and the searchview.. Any explanation of this behavior needing useffect?
"use client";
imports...
const SearchView = <T,>({
resourceName,
initialResources,
createResourceHref,
searchService,
}: {
resourceName: string;
initialResources: T[];
createResourceHref: string;
searchService: (search: string) => Promise<FetchResponse<T[]>>;
}) => {
const [resources, setResources] = useState<T[]>(initialResources);
return (
<>
<SearchBox<T>
resource={resourceName}
addHref={createResourceHref}
searchService={searchService}
setResources={setResources}
/>
<Container>
<div className="flex w-full flex-col items-stretch justify-center gap-[10px]">
{resources.length === 0 ? (
<p className="">
Sin resultados
</p>
) : (
resources.map((resource, index) => {
if (isTeacher(resource))
return (
<TeacherCard
key={index}
id={(resource as Teacher).id}
name={(resource as Teacher).name}
lastname={(resource as Teacher).lastname}
isActive={(resource as Teacher).isActive}
profileImageUrl={(resource as Teacher).profileImageUrl}
/>
);
if (isSchool(resource))
return (
<SchoolCard
key={index}
id={(resource as School).id}
name={(resource as School).name}
/>
...
};
Adding this solved it:
useEffect(() => {
setResources(initialResources);
}, [initialResources]);
It turns out that the other page using the same logic was not using the searchview, but a variation of it using of it in which theres a page between the edit and the searchview.. Any explanation of this behavior needing useffect?
LeonNOP
Deepseek solved it for me:
The issue you're describing—where the UI is not updating even though the data is being revalidated—likely stems from how the resources state is managed in your SearchView component. Specifically, the resources state is initialized with initialResources, but it doesn't automatically update when initialResources changes (e.g., after revalidation).
Here’s how you can fix this:
1. Update State When initialResources Changes
The initialResources prop is passed to the component, but the resources state is only set once when the component mounts. To ensure the state updates when initialResources changes, you can use the useEffect hook.
The issue you're describing—where the UI is not updating even though the data is being revalidated—likely stems from how the resources state is managed in your SearchView component. Specifically, the resources state is initialized with initialResources, but it doesn't automatically update when initialResources changes (e.g., after revalidation).
Here’s how you can fix this:
1. Update State When initialResources Changes
The initialResources prop is passed to the component, but the resources state is only set once when the component mounts. To ensure the state updates when initialResources changes, you can use the useEffect hook.
useEffect(() => {
setResources(initialResources);
}, [initialResources]);
Answer