greypixel
greypixel
TTCTheo's Typesafe Cult
Created by greypixel on 6/27/2024 in #questions
Passing async data to server components
hey guys. I have a basic question - I'm fetching some "slow" data in a server component (at the page level). There are several components on the page that depend on it, so I'm currently awaiting that data, but obviously it means I have to wait before I get anything. What's the best way to split this up so I can use suspense? Is it to await getSlowData() in every one of the components that requires it, and use unstable_cache to make sure it's deduped? Or should I be doing const slowDataPromise = getSlowData() and have the child components await the promise passed as a prop? Or (hopefully but unlikely) I’ve missed some built in way of doing this succinctly?
2 replies
TTCTheo's Typesafe Cult
Created by greypixel on 6/21/2024 in #questions
Throttling calls to a server function in NextJS
I have a server function that can poll if a long-running event (Ethereum transaction being mined) has completed yet. The actual request checking the blockchain is obviously also async and can take a second or two. If someone hits the page when the transaction result hasn't already been stored in the db, their client will start calling a function on the server to check the status and update the db on success. If multiple people are on this page, I don't really want to poll the blockchain excessively, so I want to early exit from calls to the server function that happen too often. Will this approach work?
const lastInvocationTimes = new Map<string, number>();

export async function pollProposalTransactionAndUpdateIfResolved({
proposalId,
chainId,
transactionHash,
}: {
proposalId: Proposal["id"];
transactionHash: Hash;
chainId: number;
}) {
// unique key for the tx.
const key = `${chainId}-${transactionHash}`;
const lastInvocationTime = lastInvocationTimes.get(key);

// Check if on cooldown.
if (lastInvocationTime && lastInvocationTime + 1000 * 15 > Date.now()) {
console.debug(`polling ${transactionHash} on ${chainId} throttled`);
return;
}

// Not invoked recently.
lastInvocationTimes.set(key, Date.now());
await _pollProposalTransactionAndUpdateIfResolved({
proposalId,
chainId,
transactionHash,
});
}
const lastInvocationTimes = new Map<string, number>();

export async function pollProposalTransactionAndUpdateIfResolved({
proposalId,
chainId,
transactionHash,
}: {
proposalId: Proposal["id"];
transactionHash: Hash;
chainId: number;
}) {
// unique key for the tx.
const key = `${chainId}-${transactionHash}`;
const lastInvocationTime = lastInvocationTimes.get(key);

// Check if on cooldown.
if (lastInvocationTime && lastInvocationTime + 1000 * 15 > Date.now()) {
console.debug(`polling ${transactionHash} on ${chainId} throttled`);
return;
}

// Not invoked recently.
lastInvocationTimes.set(key, Date.now());
await _pollProposalTransactionAndUpdateIfResolved({
proposalId,
chainId,
transactionHash,
});
}
Asking because I'm not sure if all clients share the same server instance, so I don't know if lastInvocationTimes will always be correct? I'm using NextJS on vercel
2 replies
TTCTheo's Typesafe Cult
Created by greypixel on 3/1/2024 in #questions
Is it possible to render a placeholder to display while a client component loads?
I kinda wanted <suspense> to do this for me but it doesn't seem to. Let's say I have a client component (from a library) that is 100px when it renders. When I include that in my server component, the initial HTML payload just has an empty comment where it should be (<!-- -->), then when the client hydrates it pops in and suddenly what was previously 0px is now 100px. I'd like to be able to render a skeleton that disappears after the hydration, is this possible?
12 replies