Next.js Discord

Discord Forum

How to memoize `POST` request across two server components?

Answered
Crème D’Argent posted this in #help-forum
Open in Discord
Crème D’ArgentOP
Say I have 2 server components A and B. A creates an Entity with a POST request and displays content based on it, and B renders different content based on that same Entity that was created by A. How can A share the result of its POST request with B without relying on client-side state?

My first thought is for B to make a GET request for the Entity which is created by A given the ID, but that still means that A has to expose the resulting ID to B somehow.

My second thought is to cache the POST request with time-based revalidation. This feels atypical, but the docs for NextJS's Data Cache don't mention the same restriction of "only applies to GET requests" that React's request memoization has--https://nextjs.org/docs/app/building-your-application/caching#data-cache.

What are my options?
Answered by Crème D’Argent
@Shy Albatross I don't have control over the design of the server I'm making requests against nor the requirements I'm building for, so unfortunately it's not a design problem I created and can therefore fix. The POST endpoint in question is one that returns a "snapshot" given a set of arguments, sort of like "given a date, time and location, give me a snapshot of the weather forecast". You want the snapshot to be retained to potentially act on later, and making the same request now versus in a few hours could return different a different forecast, hence why it's a POST and not a GET (it is not idempotent).

However, the requirements on the client are such that we can and should show a Snapshot on page load, and then the user can decide whether or not they want to act on said Snapshot. It may still technically qualify as a side effect, but the only action the user needed to perform to get (read: create) the Snapshot was to load the page, the path and parameters of which represent the arguments of the request.

Solving this problem on the client is trivial given patterns like useEffect and useState--it's much less obvious how one would approach this on the server. In the end, I solved this using the cache function in order to manually memoize two identical POST requests made by two different server components within the same server request cycle. https://react.dev/reference/react/cache#take-and-share-snapshot-of-data
View full answer

8 Replies

Shy Albatross
"Server component creates an entity with a POST request". Well, there's your problem
why would a server component make a POST request ever, server components should just render out their stuff from the input they get
there should never be a side effect of a server component render, that includes mutations such as your POST
so you've put yourself in a dead end and now your trying to solve a problem that you yourself cause with bad design, and solving that problem proves to be non-trivial
my typical advice in a situation like this - take a step back because you can't see the forest for the trees
maybe this will help you design the solution better: https://nextjs.org/blog/security-nextjs-server-components-actions
@Shy Albatross great response
Crème D’ArgentOP
@Shy Albatross I don't have control over the design of the server I'm making requests against nor the requirements I'm building for, so unfortunately it's not a design problem I created and can therefore fix. The POST endpoint in question is one that returns a "snapshot" given a set of arguments, sort of like "given a date, time and location, give me a snapshot of the weather forecast". You want the snapshot to be retained to potentially act on later, and making the same request now versus in a few hours could return different a different forecast, hence why it's a POST and not a GET (it is not idempotent).

However, the requirements on the client are such that we can and should show a Snapshot on page load, and then the user can decide whether or not they want to act on said Snapshot. It may still technically qualify as a side effect, but the only action the user needed to perform to get (read: create) the Snapshot was to load the page, the path and parameters of which represent the arguments of the request.

Solving this problem on the client is trivial given patterns like useEffect and useState--it's much less obvious how one would approach this on the server. In the end, I solved this using the cache function in order to manually memoize two identical POST requests made by two different server components within the same server request cycle. https://react.dev/reference/react/cache#take-and-share-snapshot-of-data
Answer