Problem: I'm working with Next.js 15 and trying to update a server component's UI after a client component triggers a server action.
Here's the simplified setup: Client Component
'use client';
import { updateText } from './parent_comp';
export default function ClientComp() {
const handleClick = async () => {
await updateText('devtz007'); // Sends new data to the server
};
return (
<button
onClick={handleClick}
style={{ color: 'black', background: 'coral' }}
>
Send Text
</button>
);
}
Server Component + Action
'use server';
import ClientComp from './client_comp';
import { revalidatePath } from 'next/cache';
let text = 'initial text';
export async function updateText(newText: string): Promise<string> {
text = newText;
// revalidatePath('/example_page'); // This re-renders the page, but I want a
more targeted update!
return text;
}
export default async function ParentComp() {
return (
<>
<p style={{ color: 'green', backgroundColor: 'coral' }}>
Received Text: {text}
</p>
<ClientComp />
</>
);
}
What I’ve Tried
revalidatePath() works but refreshes the entire page. I updated my
code to use revalidateTag() and added cache tags like textUpdate:
// Server action with revalidateTag export async function updateText( newText: string, options: { next: { tags: string[] } }, ) { if (options.next.tags.includes('textUpdate')) { text = newText; revalidateTag('textUpdate'); // Should trigger the related components } }
And the component:
export default async function ParentComp() {
return (
<>
<p style={{ color: 'green', backgroundColor: 'coral' }}>{text}</p>
<ClientComp />
</>
);
}
Issue
- Is revalidateTag() re-rendering just the related portion (e.g.,
Received Text
) or the whole page? - If I use ClientComp on another page, clicking the button does not immediately update the ParentComp without a manual page refresh.
- I don’t want to use router.refresh() because it refreshes the full page.
- What's the intended pattern in Next.js 15 to partially refresh components after an action without reloading the whole page?