Basic state
The useState reference opens with four basic state shapes: a counter, a text field, a checkbox, and a form. First steps covered the counter. Here are the other three, as streams.
The pattern is always the same:
- State lives in a
Subject(or aBehaviorSubjectwhen it has a current value). - Plain event handlers push into it with
.next(...). - Components read it with a hook.
One split to remember: controlled inputs read useSyncObservable. The caret and IME need synchronous updates. Everything else defaults to useObservable.
Text field (string)
Checkbox (boolean)
This one uses a module-scoped BehaviorSubject. It holds a current value and emits it synchronously, so the first render already has the real state. And because it lives outside the component, it survives remounts and can be shared or composed with other streams.
Compare with the text field above, where useState(() => new Subject()) keeps the state per component instance.
Form (two variables)
Two independent pieces of state, just like two useState calls. Also a preview of the hook split: the name feeds a controlled input (useSyncObservable), while the age only feeds rendering (useObservable).
Where to next
So far streams have only replaced useState. The payoff starts when state involves time. Continue to Timers & time ago.