Cannot infer intended usage of current time with `Date.now()`, `Date()`, or `new Date()` in a Server Component
Why This Error Occurred
Reading the current time in a Server Component can be ambiguous. Sometimes you intend to capture the time when something was cached, other times you intend to capture the time of a user Request. You might also be trying to measure runtime performance to track elapsed time.
Depending on your use case you might use alternative time APIs like performance.now()
, you might cache the time read with "use cache"
, or you might communicate that the time must be evaluated on each request by guarding it with await connection()
or moving it into a Client Component.
Possible Ways to Fix It
Performance use case
If you are using the current time for performance tracking with elapsed time use performance.now()
.
Before:
export default async function Page() {
const start = Date.now();
const data = computeDataSlowly(...);
const end = Date.now();
console.log(`somethingSlow took ${end - start} milliseconds to complete`)
return ...
}
After:
export default async function Page() {
const start = performance.now();
const data = computeDataSlowly(...);
const end = performance.now();
console.log(`somethingSlow took ${end - start} milliseconds to complete`)
return ...
}
Note: If you need report an absolute time to an observability tool you can also use
performance.timeOrigin + performance.now()
.
Cacheable use cases
If you want to read the time when some cache entry is created (such as when a Next.js page is rendered at build-time or when revalidating a static page), move the current time read inside a cached function using "use cache"
.
Before:
async function InformationTable() {
const data = await fetch(...)
return (
<section>
<h1>Latest Info...</h1>
<table>{renderData(data)}</table>
</section>
)
}
export default async function Page() {
return (
<main>
<InformationTable />
Last Refresh: {new Date().toString()}
</main>
)
}
After:
async function InformationTable() {
"use cache"
const data = await fetch(...)
return (
<>
<section>
<h1>Latest Info...</h1>
<table>{renderData(data)}</table>
</section>
Last Refresh: {new Date().toString()}
</>
)
}
export default async function Page() {
return (
<main>
<InformationTable />
</main>
)
}
Request-time use case
Moving time to the client
If the current time must be evaluated on each user Request consider moving the current time read into a Client Component. You might also find that this is more convenient when you want to do things like update the time independent of a page navigation. For instance imagine you have a relative time component. Instead of rendering the relative time in a Server Component on each Request you can render the relative time when the Client Component renders and then update it periodically.
If you go with this approach you will need to ensure the Client Component which reads the time during render has a Suspense boundary above it. You may be able to improve the loading experience by adopting a more narrowly scoped Suspense boundary. Use your judgement about what kind of UI loading sequence you want your users to experience to guide your decision here.
Before:
function RelativeTime({ when }) {
return computeTimeAgo(new Date(), when)
}
export default async function Page() {
const data = await ...
return (
<main>
...
<Suspense>
<RelativeTime when={data.createdAt} />
</Suspense>
</main>
)
}
After:
'use client'
import { useReducer } from 'react'
export function RelativeTime({ when }) {
const [_, update] = useReducer(() => ({}), {})
const timeAgo = computeTimeAgo(new Date(), when)
// Whenever the timeAgo value changes a new timeout is
// scheduled to update the component. Now the time can
// rerender without having the Server Component render again.
useEffect(() => {
const updateAfter = computeTimeUntilNextUpdate(timeAgo)
let timeout = setTimeout(() => {
update()
}, updateAfter)
return () => {
clearTimeout(timeout)
}
})
return timeAgo
}
import { RelativeTime } from './relative-time'
export default async function Page() {
const data = await ...
return (
<main>
...
<Suspense>
<RelativeTime when={data.createdAt} />
</Suspense>
</main>
)
}
Note: Accessing the current time in a Client Component will still cause it to be excluded from prerendered server HTML but Next.js allows this within Client Components because it can either compute the time dynamically when the user requests the HTML page or in the browser.
Guarding the time with await connection()
It may be that you want to make some rendering determination using the current time on the server and thus cannot move the time read into a Client Component. In this case you must instruct Next.js that the time read is meant to be evaluated at request time by preceding it with await connection()
.
Next.js enforces that it can always produce at least a partially static initial HTML page so you will also need to ensure that there is a Suspense boundary somewhere above this component that informs Next.js about the intended fallback UI to use while prerendering this page.
Before:
export default async function Page() {
const currentTime = Date.now()
if (currentTime > someTriggerDate) {
return <SpecialBanner />
} else {
return <NormalBanner />
}
}
After:
import { Suspense } from 'react'
import { connection } from 'next/server'
async function BannerSkeleton() {
...
}
export default async function Page() {
return <Suspense fallback={<BannerSkeleton />}>
<DynamicBanner />
</Suspense>
}
async function DynamicBanner() {
await connection();
const currentTime = Date.now();
if (currentTime > someTriggerDate) {
return <SpecialBanner />
} else {
return <NormalBanner />
}
}
Useful Links
Was this helpful?