chapter thirteen

13 Data binding and reactivity

 

This chapter covers

  • Thinking reactively with state, derived data, and effects
  • Binding state to the DOM in both directions, without a framework
  • Choosing among render functions, stores, proxies, and signals
  • Managing application state with a single source of truth
  • Validating data at every boundary

In the previous chapter, we covered how data reaches a Vanilla app and where it is stored. This chapter is about the other half of working with data: keeping the user interface in sync with it as it changes.

At the center of the chapter is dynamic data binding: how a Vanilla app keeps its interface in sync with changing data, in both directions, without a framework runtime. That is where the platform most often surprises developers with how much it already gives you, so it is where we spend the most time.

Some examples reuse the requestJSON() helper introduced in the previous chapter; you can treat it as any small fetch() wrapper that returns parsed JSON and throws on HTTP errors. If you come from React or Angular, this chapter is about recognizing reactivity, state, and validation without framework-specific ceremony.

13.1 Reactive thinking

Reactive programming can sound abstract if you first meet it through a framework. For our purposes, it means something simpler: when data changes, every part of the UI that depends on that data should be updated predictably.

There are three pieces:

13.2 Data binding techniques

13.2.1 Direct DOM binding

13.2.2 Derived bindings

13.2.3 A render function with queueMicrotask()

13.2.4 Binding through data-* attributes

13.2.5 Binding with template strings

13.2.6 Binding with <template>

13.2.7 EventTarget stores

13.2.8 Proxy

13.2.9 Signals through a micro-library

13.2.10 Choosing a binding pattern

13.3 State management

13.3.1 Design patterns

13.4 Data validation

13.5 Summary