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

[Guide] Build a Habit Tracker - implementation notes

Started by Theo Bennett
guidehabitsderived statefreshness postureroutingrender cadence

The Habit Tracker guide is explicit about its UX primitive: re-rendering. It treats "always ready" UI as the goal by storing streaks and chart-ready aggregates directly in state, and it introduces a "freshness posture" toggle (warm vs hot) that intentionally increases cadence and renders that posture as evidence on the shell.

Read the guide

Have you shipped a 'freshness posture' control like this, and did users actually perceive the difference? How do you decide what derived values to store (streaks, month grid) vs what to compute opportunistically? If the file router is the map and the component router is the motion, how do you keep mode/panel state from becoming invisible?

Comments (10)

Back to latest
Maya Henson
Jan 04, 2023 · 04:06 PM

Storing chart-ready aggregates is a good move. The worst feeling is a chart that lags because it recomputes everything on each toggle.

If the app is 'always ready', the graph should be too.

Dmitri Kline
Jan 04, 2023 · 04:14 PM

The guide's posture matches the docs emphasis on derived state and observable behavior.

If you increase cadence ('hot'), you should also render the posture so debugging is honest.

Related: Performance and Rendering Best Practices and State Management Best Practices.

Salma Qureshi
Jan 04, 2023 · 04:22 PM

Warm vs hot is a fun idea because it forces you to name the tradeoff: more motion vs more battery/CPU.

If the user can choose, you also need to remember the choice globally (route state is a good fit).

Keira Santos
Jan 04, 2023 · 04:33 PM

Counterpoint: increasing re-render cadence can hide inefficient rendering by brute force.

I'd pair it with a simple budget marker so hot mode can't silently turn into 'slow but busy'.

Priya Liao
Jan 04, 2023 · 04:46 PM

The file router vs component router split is actually a nice way to talk about tabs/overlays.

But only if you render which mode/panel you're in; otherwise support can't reproduce anything.

Related: Routing and Navigation.

Hana Saito
Jan 04, 2023 · 04:58 PM

We shipped a warm/hot toggle (not called that) and users did notice it, but only in the negative direction (battery/heat).

It was still useful as a support tool: you can ask a user to flip to warm mode and see if the jitter disappears.

Avery Chen
Jan 04, 2023 · 05:11 PM

Storing streak + weekly totals is the right kind of derived state: it removes compute from interactions.

The one thing I'd add is provenance so you can tell when streaks were last re-derived (especially if checks sync is async).

Dmitri Kline
Jan 04, 2023 · 05:24 PM

Minimal pattern we used for habit derivations (very similar to the guide):

ts
doc.write('streak', computeStreak(doc.read('checksByDay'), doc.read('today')));
doc.write('weeklyTotals', computeWeeklyTotals(doc.read('checksByDay'), doc.read('today')));
doc.write('derivedAt', Date.now());

Then render data-derived-at + data-freshness so a screenshot carries both the cadence and the last derivation time.

Keira Santos
Jan 04, 2023 · 05:38 PM

Counterpoint to the cadence toggle: if hot mode is supposed to make things feel better, it can also become a crutch.

Teams might stop fixing expensive renders because "users can just use warm".

Theo Bennett
Jan 04, 2023 · 05:43 PM

That's fair. I think the guide's intent is to make cadence a named tradeoff, not a hidden one.

If you render the mode and budget lane together, hot mode becomes a signal to improve the route, not a permanent escape hatch.

Keira Santos
Jan 04, 2023 · 05:46 PM

Yeah, pairing it with a budget marker makes it feel less like "turn on chaos mode".

Benji Rios
Jan 04, 2023 · 05:58 PM

I like the way the guide forces you to name the contract keys (freshness, mode, panel).

Habits apps are deceptively simple until back/forward and editing modes show up; named keys + rendered evidence keeps it from turning into hidden UI state.