React Forum
Blog & Guide Responses
Jan 26, 2023 · 04:00 PM

[Guide] Build a Fitness Dashboard (Profiler Signals Optional) - implementation notes

Started by Morgan Patel
guidefitnessdashboardrender tick posturekey remountingmemoization stancestored derived cardsfreshness switches

The Fitness Dashboard guide frames performance as a route posture problem: decide "tick cadence" and remount boundaries in the route contract, then store derived card outputs so the dashboard stays stable even when the underlying data churns. I like the premise that the profiler is optional—what matters is making performance decisions explicit and observable.

Read the guide

How did you decide which cards should remount on identity changes versus preserve local UI state? Did you encode a render tick posture (warm/cool) as route state, or keep it as a local toggle? What memoization stance worked in practice: memo everything, memo nothing, or memo only derived selectors? How did you implement "freshness switches" without making the UI feel like it randomly resets?

Comments (18)

Back to latest
Marisol Vega
Jan 30, 2023 · 08:20 PM

Big win for me was treating remount keys as part of the contract.

Once you commit to a remount boundary, performance bugs turn into normal state bugs.

Dmitri Kline
Feb 07, 2023 · 07:07 AM

We made the remount boundary explicit on the card shell. It looks like this:

tsx
function CardShell({ athleteId, cardKey, children }: any) {
  const identityKey = `${athleteId}:${cardKey}`;
  return <section key={identityKey} data-card={cardKey}>{children}</section>;
}

Now when someone says "my chart reset", we can point to the identity key and decide if it's intended.

Keira Santos
Feb 16, 2023 · 12:12 PM

Counterpoint: too many remount keys make the dashboard feel flaky.

We only remount when the semantics change (athlete swap, date range swap). UI mode toggles should not remount.

Morgan Patel
Feb 20, 2023 · 04:40 AM

Same. "Freshness" isn't a synonym for "reset".

We treated it like: reset only when the user's mental model should reset.

Grace McCoy
Mar 03, 2023 · 03:03 AM

We encoded tick posture in route state because it affects everything (requests, polling, derived summaries).

If it's local, two panels disagree and you can't reason about it.

Jasper Nguyen
Mar 19, 2023 · 06:18 PM

Memo stance: we memo only the derived selectors and keep components dumb.

If you memo everything, you end up debugging memoization instead of UI.

Nina Kapoor
Apr 06, 2023 · 06:06 AM

Stored derived cards were the only way our dashboard stayed coherent across route switches.

Otherwise each card derives slightly differently and you get "why is this number different" arguments.

Camille Duarte
Apr 24, 2023 · 10:10 AM

We rendered evidence for tick posture + remount version so screenshots tell the story:

tsx
<main
  data-tick-posture={route.tick}
  data-freshness={route.freshness}
  data-remount-version={route.remountVersion}
/>

It's not pretty, but it's extremely effective.

Owen Price
May 13, 2023 · 05:05 AM

Freshness switches: we used a small "confirm" affordance if the switch would reset filters.

Users hate surprise resets even when they're "correct".

Benji Rios
May 31, 2023 · 10:22 PM

Counterpoint: storing derived cards can hide performance problems.

If the derive is expensive and you do it too often, you just moved the cost somewhere else.

Amina Farouk
Jun 04, 2023 · 11:11 AM

True, but I like it because it forces you to choose *when* to pay the cost (on mutation) rather than paying it on every render.

It's also easier to measure because the derive is a named path.

Lina Ortega
Jun 21, 2023 · 04:04 AM

Docs tie-in: the idea of explicit posture matches the perf docs pretty closely.

Related: Performance and Rendering (Best Practices) and Routing and Navigation.

Sofia Valdez
Jul 14, 2023 · 12:34 PM

We used a "cool tick" mode that freezes derived cards for 10s windows and it made scrolling smoother.

The key is rendering the tick window as evidence so people don't think the data is stale by accident.

Priya Liao
Aug 09, 2023 · 09:09 AM

A practical trick: keep chart hover state local and never store it. It's not a contract.

We store only the derived summary numbers so navigation stays stable.

Theo Bennett
Sep 03, 2023 · 03:03 AM

Memoization stance that worked for us: memo only at the boundary of "raw data -> derived card".

Everything after that is render-only and doesn't need cleverness.

Rowan Pierce
Oct 06, 2023 · 04:16 PM

Remount boundaries also helped with correctness: we stopped leaking previous athlete state into new views.

Performance aside, it fixed a bunch of "wrong data" bugs.

Tomas Rivera
Oct 29, 2023 · 06:06 AM

If you keep tick posture in route state, make sure back/forward replays it correctly.

Otherwise the dashboard feels like it has moods.

Salma Qureshi
Nov 18, 2023 · 06:18 PM

The "profiler optional" framing is good for teams. It lowers the bar: you can still do coherent perf work without being an expert.

Explicit contracts + evidence gets you most of the way.

Evan Brooks
Dec 02, 2023 · 02:02 AM

Freshness switches were easiest when we treated them like a mode: switch -> remount version increments -> derived cards recompute once.

Trying to make it incremental led to a lot of partial updates and confusing UI.

Harper Iqbal
Dec 23, 2023 · 11:23 PM

I liked that the guide doesn't treat memoization like a superstition.

It's a stance: decide where memo boundaries belong and make them part of the route contract.