Skip to content

Memoize and lazy-load the dashboard widgets to cut initial render and Recharts costΒ #531

Description

@Baskarayelu

πŸ“‹ Description

The dashboard (app/dashboard/page.tsx) renders many widgets eagerly β€” components/Dashboard/MoneyDistributionWidget.tsx, components/Dashboard/SixMonthTrendsWidget.tsx, components/Dashboard/SavingsByGoalWidget.tsx, components/Dashboard/RecentTransactionsWidget.tsx, and the split widget components/CurrentMoneySplitWidget.tsx. The chart widgets pull in Recharts (heavy) and re-render on every parent state change. There's a separate open issue for the Insights charts; this targets the dashboard widgets specifically.

This issue lazy-loads the chart widgets and memoizes the static ones to reduce the dashboard's initial bundle and re-render churn.

Why this matters: the dashboard is the most-visited authenticated screen. Eagerly importing Recharts for every widget inflates the first load and makes unrelated state changes repaint charts. Lazy + memo is a measurable, low-risk win.

🎯 Requirements & Context

Functional requirements

  • Lazy-load the Recharts-backed widgets (next/dynamic or React.lazy + Suspense) with skeleton fallbacks from components/ui/LoadingSkeletons.tsx.
  • Wrap pure widgets in React.memo and stabilize props with useMemo/useCallback where the parent re-renders frequently.
  • Verify no layout shift when a lazy widget resolves (reserve space).
  • Confirm behavior parity with the current dashboard (no regressions in data or interactivity).

Context & constraints

  • Don't change widget APIs unnecessarily β€” this is a perf refactor.
  • Capture a before/after measurement (bundle delta and/or render count) in the PR.

πŸ› οΈ Suggested Execution

1. Fork & branch

git checkout -b perf/dashboard-widget-lazy-memo

2. Implement changes

  • Convert chart widgets to dynamic imports with skeleton fallbacks.
  • Memoize static widgets and stabilize props.
  • Document the perf approach + measurements in docs/.
  • Edge cases: reduced-motion skeletons, no layout shift, error fallback still works (WidgetErrorState), responsive, SSR/CSR boundaries respected.

3. Test & commit

npm run build
npm run lint
npx tsc --noEmit
npm run test:coverage

Example commit message

perf(dashboard): lazy-load chart widgets and memoize static ones

Defers Recharts-backed widgets behind dynamic imports with skeleton fallbacks
and memoizes pure widgets to cut initial load and re-render churn.

βœ… Acceptance Criteria & Guidelines

Requirement Target
Chart widgets lazy-loaded with skeletons Required
Before/after measurement in PR Required
No layout shift on resolve Required
Behavior parity (no regressions) Required
Responsive + reduced-motion Required
build + lint + tsc --noEmit clean Required
Timeframe 96 hours from assignment

πŸ’¬ Community & Support

Questions and design discussion β€” join the RemitWise contributor community on Discord: https://discord.gg/CtQuPZFMA

Comment to claim. πŸš€

Metadata

Metadata

Assignees

Type

Fields

No fields configured for Task.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions