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

[Guide] Build a Todo App - implementation notes

Started by Priya Liao
guidetodosroute shellderived stateFielduseRenderEffect

The Todo guide is a good example of the repo patterns applied to something small: a route shell, a global route store for cross-screen behavior, a screen document with stored derived state, and a Field that keeps DOM truth and state truth alive together so you can move between input postures without rewriting.

Read the guide

Do you actually store derived state like visibleItems, or do you compute it in render and rely on memoization? How do you decide when to commit input changes (keystroke vs blur vs submit) when you also want deterministic review surfaces? If filters are route state, how do you keep back/forward behavior predictable when the list is also mutating?

Comments (10)

Back to latest
Noah Vance
Jan 01, 2023 · 04:06 PM

The multiple sources of truth for Field is controversial, but it has saved us in migrations.

Dmitri Kline
Jan 01, 2023 · 04:13 PM

The guide is quietly consistent with the docs posture: store derived state so the UI renders instantly and predictably.

Related: Core Concepts (Best Practices) and Forms and Validation Best Practices.

Amina Farouk
Jan 01, 2023 · 04:21 PM

We implemented the derived-state approach almost exactly and it made debugging much easier:

ts
function deriveVisible(state: any, visibility: 'all' | 'open' | 'done') {
  const items = state.read('items');
  const visible = visibility === 'done' ? items.filter((t: any) => t.done) :
    visibility === 'open' ? items.filter((t: any) => !t.done) : items;
  state.write('visibleItems', visible);
}

It is more writes, but it is a stable contract in the screen doc.

Keira Santos
Jan 01, 2023 · 04:33 PM

Counterpoint: storing derived lists can turn into a consistency trap if you do not re-derive on every mutation path.

We had a bug where the source list updated but the derived list did not because one action forgot to call derive.

Priya Liao
Jan 01, 2023 · 04:39 PM

Yes, that is the cost. The guide leans on render-visible effects to keep derivation on the happy path.

In practice we also centralize mutations and call derive in one place so you cannot forget it.

Keira Santos
Jan 01, 2023 · 04:44 PM

Centralizing mutation + derive makes it feel less fragile.

Hana Saito
Jan 01, 2023 · 04:55 PM

On commit timing: blur-to-commit worked for us because it made review surfaces stable without making typing feel laggy.

We still kept a final submit for anything that touched the network.

Grace McCoy
Jan 01, 2023 · 05:04 PM

Back/forward got better when we treated filters as route truth and list mutations as document truth.

The route decides visibility; the document decides what exists.

Camille Duarte
Jan 01, 2023 · 05:16 PM

A misunderstanding I had at first: I assumed storing derived state was a micro-optimization.

In this guide it is more about determinism and supportability than speed.

Rowan Pierce
Jan 01, 2023 · 05:29 PM

If you are using route state for filters, I would also render it as evidence in the shell.

It makes user bug reports much easier to interpret.

Benji Rios
Jan 01, 2023 · 05:44 PM

The guide is small, but it sets the tone: treat even a Todo app like a route contract, not a toy.

Inez Park
Jan 01, 2023 · 05:58 PM

I would love to see an appendix on testing the derived state invariants. That is where we usually regress.