fix: nexu modal should re-show on refresh but not on SPA nav#2274
fix: nexu modal should re-show on refresh but not on SPA nav#2274
Conversation
sessionStorage persists across page refresh, which prevented the modal from re-appearing for users who haven't opted out. A module-level variable resets on refresh but persists across SPA navigation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
📝 WalkthroughWalkthroughRefactored NexuModal gating mechanism from session-based storage to module-level page-load flag. Removed sessionStorage usage including SESSION_KEY constant and associated getItem/setItem checks. Modal now tracks visibility state using a page-load-scoped variable instead of browser session storage. Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~8 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Deploying refly-branch-test with
|
| Latest commit: |
f381676
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://9ea7d654.refly-branch-test.pages.dev |
| Branch Preview URL: | https://fix-nexu-modal-spa-nav.refly-branch-test.pages.dev |
There was a problem hiding this comment.
🧹 Nitpick comments (3)
packages/ai-workspace-common/src/components/nexu-promotion/NexuModal.tsx (3)
148-148: Consider avoiding inline arrow function in onChange handler.The inline arrow function
(e) => handleNeverShowChange(e.target.checked)creates a new function reference on every render.♻️ Proposed fix
Update
handleNeverShowChangeto accept the event directly:- const handleNeverShowChange = useCallback((checked: boolean) => { - setNeverShow(checked); + const handleNeverShowChange = useCallback((e: { target: { checked: boolean } }) => { + setNeverShow(e.target.checked); }, []);Then simplify the JSX:
- onChange={(e) => handleNeverShowChange(e.target.checked)} + onChange={handleNeverShowChange}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/ai-workspace-common/src/components/nexu-promotion/NexuModal.tsx` at line 148, The inline arrow in the JSX causes a new function each render; update the handler signature of handleNeverShowChange to accept the ChangeEvent<HTMLInputElement> (or generic event) instead of a boolean so it can read e.target.checked internally, then replace the JSX onChange={(e) => handleNeverShowChange(e.target.checked)} with onChange={handleNeverShowChange} in NexuModal.tsx to avoid recreating the function each render and keep behavior identical.
98-102: Consider extracting inline style objects to constants.The inline objects
style={{ maxWidth: 640 }}andstyles={{ body: { padding: 0 } }}are recreated on every render.♻️ Proposed fix
const NEXU_URL = 'https://nexu.io'; const STORAGE_KEY = 'nexu_modal_dismissed'; +const MODAL_STYLE = { maxWidth: 640 }; +const MODAL_BODY_STYLES = { body: { padding: 0 } }; // Module-level flag: resets on page refresh, persists across SPA navigation let hasShownThisPageLoad = false;Then in the JSX:
width="fit-content" - style={{ maxWidth: 640 }} + style={MODAL_STYLE} className="nexu-modal" - styles={{ - body: { padding: 0 }, - }} + styles={MODAL_BODY_STYLES}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/ai-workspace-common/src/components/nexu-promotion/NexuModal.tsx` around lines 98 - 102, Extract the inline style objects used in the NexuModal component into stable constants to avoid recreating them each render: create named constants (e.g., MODAL_CONTAINER_STYLE = { maxWidth: 640 } and MODAL_BODY_STYLES = { body: { padding: 0 } }) at module scope and replace the JSX props style and styles on the Modal/element in NexuModal.tsx with those constants; ensure the constants are immutable (const) and referenced by the component (NexuModal) instead of using inline objects.
76-89: Memoize thefeaturesarray to prevent unnecessary re-renders.Per coding guidelines, avoid inline object/array creation in render and use
useMemofor complex object creation. Thefeaturesarray is recreated on every render.♻️ Proposed fix
+ const features = useMemo( + () => [ + { + key: 'message', + icon: <LuMessageSquare size={18} />, + text: t('nexuPromotion.modal.feature1'), + }, + { + key: 'shield', + icon: <LuShield size={18} />, + text: t('nexuPromotion.modal.feature2'), + }, + { + key: 'fork', + icon: <LuGitFork size={18} />, + text: t('nexuPromotion.modal.feature3'), + }, + ], + [t], + ); - const features = [ - { - icon: <LuMessageSquare size={18} />, - text: t('nexuPromotion.modal.feature1'), - }, - { - icon: <LuShield size={18} />, - text: t('nexuPromotion.modal.feature2'), - }, - { - icon: <LuGitFork size={18} />, - text: t('nexuPromotion.modal.feature3'), - }, - ];Then update the map to use the stable key:
- <div - key={index} + <div + key={feature.key}As per coding guidelines: "Always use useMemo for expensive computations or complex object creation in React" and "Always use proper key props when rendering lists in React (avoid using index when possible)".
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/ai-workspace-common/src/components/nexu-promotion/NexuModal.tsx` around lines 76 - 89, The features array in NexuModal.tsx is recreated on every render causing unnecessary re-renders; wrap its creation in React.useMemo (e.g., memoize the const features = [...] block) so it returns a stable reference, and when mapping features to elements use a stable unique key (for example derive key from text or a fixed id on each feature) instead of the array index to prevent key-related rendering issues.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@packages/ai-workspace-common/src/components/nexu-promotion/NexuModal.tsx`:
- Line 148: The inline arrow in the JSX causes a new function each render;
update the handler signature of handleNeverShowChange to accept the
ChangeEvent<HTMLInputElement> (or generic event) instead of a boolean so it can
read e.target.checked internally, then replace the JSX onChange={(e) =>
handleNeverShowChange(e.target.checked)} with onChange={handleNeverShowChange}
in NexuModal.tsx to avoid recreating the function each render and keep behavior
identical.
- Around line 98-102: Extract the inline style objects used in the NexuModal
component into stable constants to avoid recreating them each render: create
named constants (e.g., MODAL_CONTAINER_STYLE = { maxWidth: 640 } and
MODAL_BODY_STYLES = { body: { padding: 0 } }) at module scope and replace the
JSX props style and styles on the Modal/element in NexuModal.tsx with those
constants; ensure the constants are immutable (const) and referenced by the
component (NexuModal) instead of using inline objects.
- Around line 76-89: The features array in NexuModal.tsx is recreated on every
render causing unnecessary re-renders; wrap its creation in React.useMemo (e.g.,
memoize the const features = [...] block) so it returns a stable reference, and
when mapping features to elements use a stable unique key (for example derive
key from text or a fixed id on each feature) instead of the array index to
prevent key-related rendering issues.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 28188112-478a-42f8-bc30-d67b4a8ffa78
📒 Files selected for processing (1)
packages/ai-workspace-common/src/components/nexu-promotion/NexuModal.tsx
Summary
sessionStoragewith a module-level flag for tracking whether the nexu modal has been shownsessionStoragepersists across page refresh, which incorrectly prevented the modal from re-appearing for users who haven't checked "don't show again"Test plan
🤖 Generated with Claude Code
Summary by CodeRabbit