[Bug/Feature Request]: `usePerformanceMarks` has ID generation incompatible with Next.js Partial Prerendering
Maintainers usually reply within 2 days
@amanabiy is already working on this.
Since Oct 1, 2026.
Assessment
This issue has not been assessed yet.
Description
Description
Summary: usePerformanceMarks calls Math.random()/Date.now() during initial render, breaking Next.js Partial Prerendering
Premise
Next.js Partial Prerendering (PPR) executes the React render pass ahead of time to produce a static shell. During this prerender pass, Next.js will report an error for any unstable values from non-deterministic operations.
The usePerformanceMarks hook currently derives its instance id from useRandomId which is evaluated during prerender with an expression based on unstable values
idRef.current = `${counter++}-${Date.now()}-${Math.round(Math.random() * 10000)}`;
Even though this value is not immediately injected into the UI (since useDOMAttribute defers it), Next.js still reports an error from the potential instability for any Cloudscape component with usePerformanceMarks (e.g. Button, Table). This is notably problematic since the SideNavigation component for AppLayout has an instance of Button.
Proposal
Replace the random generator for the id in usePerformanceMarks with the existing useUniqueId which is backed by React.useId on React 18+.
Change: in src/internal/hooks/use-performance-marks/index.ts
- import { useRandomId } from '../use-unique-id';
+ import { useUniqueId } from '../use-unique-id';
...
- const id = useRandomId();
+ const id = useUniqueId();
React.useId produces unique and stable identifiers that are consistent between server and client.
This was previously flipped in #2345 for an unclear reason:
- There shouldn't be any hydration concerns since the value is not injected into the DOM until the client-side hook runs
- With the React IDs, there might be a need to escape or transform the colon characters (e.g.
:r0:) to be compatible with selector logic, e.g.[data-analytics-performance-mark="${id}"])
Possible Alternative
Since the value is only ever used on the client (written in useEffect, read back from the perf mark on the client), the generation could be deferred until the ID is consumed (at the cost of messier code), see Lazy-initialize a stable ID with useRef
function getOrCreateId(ref: RefObject<string | null>) {
if (ref.current === null) {
ref.current = ... // generate
}
return ref.current;
}
function usePerformanceMarks(...) {
const idRef = useRef<string | null>(null);
const getId = useCallback(() => getOrCreateId(idRef), []);
// update useDOMAttribute to accept both value or getter function
// call `getId` inside `useEffect` for `instanceIdentifier
}
Or alternatively provide a way to opt out of performance marks
Reproduction
- Create Next.js 16 application and install Cloudscape components
- Enable
cacheComponentsinnext.config.ts - Add a Cloudscape
Buttonto any page - Load page from dev server or attempt to build app
- Observe error
Error: Route "/": Next.js encountered the unstable value
Date.now()in a Client Component.
This value would be evaluated during the prerender, instead of recomputed on each visit.
Code of Conduct
- I agree to follow this project's Code of Conduct
- I checked the current issues for duplicate requests
- Dominant language
- TypeScript
- Stars
- 2.7k
- Forks
- 248
- Avg merge
- 3d 14h
- Merged PRs (30d)
- 83
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from cloudscape-design/components
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
cloudscape-design/components#5184 · 1 comment ·
Maintainers usually reply within 2 days
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
cloudscape-design/components#5152 · 1 comment ·
Maintainers usually reply within 2 days
-
enhancement
Difficulty 5/5 Over a week Newbie friendliness 15/100
cloudscape-design/components#5149 · 1 comment ·
Maintainers usually reply within 2 days
-
bug
Difficulty 4/5 3-5 days Newbie friendliness 45/100
cloudscape-design/components#5117 · 2 comments ·
Maintainers usually reply within 2 days
-
Difficulty 5/5 Over a week Newbie friendliness 35/100
cloudscape-design/components#5106 · 1 comment ·
Maintainers usually reply within 2 days
All issues in cloudscape-design/components
Similar issues
-
area: image-engine bug priority: low
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
snapotter-hq/SnapOtter#3885 ·
Maintainers usually reply within 1 day
-
Mend: dependency security vulnerability
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
Maintainers usually reply within 3 days
-
pending triage
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
Maintainers usually reply within 1 day
-
bug P3 UI/UX
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
Maintainers usually reply within 1 day
-
clawsweeper:fix-shape-clear clawsweeper:queueable-fix clawsweeper:source-repro impact:ux-friction issue-rating: 🦞 diamond lobster no-stale P3
Difficulty 2/5 1-3 hours Newbie friendliness 73/100
openclaw/openclaw#182077 · 1 comment · 1 reaction ·
Maintainers usually reply within 1 day