Integration: Optimistic UI
Relevant source files
The following files were used as context for generating this wiki page:
keyfold provides a mechanism for optimistic UI reconciliation by folding partial deltas into a nested state tree. It functions as a JSON Merge Patch implementation that specifically understands keyed lists, allowing for granular updates to state without the risk of list corruption often associated with index-based merging. By utilizing identity-keyed reconciliation, the library ensures that UI updates—such as form autosaves, websocket reducers, or configurator recalculations—remain consistent with an authoritative source.
Sources: README.md:3-8, README.md:20-25
The system is designed to be immutable and deterministic. When a delta is applied, the original state remains untouched, and structural sharing is leveraged to return the original references for sibling branches that haven't changed. This is particularly beneficial for UI frameworks that rely on reference equality to determine when to re-render components.
Sources: AGENTS.md:16-25, test/laws.test.ts:98-109
Core Architecture and Data Flow
The integration revolves around a "fold" operation where a partial Delta is merged into a Base state tree. The architecture distinguishes between plain objects (which are deep-merged), keyed lists (which are reconciled by identity), and unkeyed arrays/scalars (which are replaced wholesale).
Reusable Merger Logic
The createMerger function compiles configuration once to create a reusable folding function. This function takes a base state and a delta, returning a new state tree.
The diagram shows the flow from configuration to the generation of a new immutable state through various folding strategies.
Sources: src/merge.ts:13-25, README.md:43-52
Reconciliation Mechanism
Unlike standard merging tools that use array indices, keyfold uses stable identity fields (strings or numbers) to match items in a list. This prevents "item duplication" or "index shifting" errors during optimistic updates.
| Feature | Behavior | Source |
|---|---|---|
| Object Merging | Deep-merges own enumerable fields. | src/merge.ts:51-55 |
| Keyed Lists | Matches by keyBy identity; preserves order; appends new items. | src/reconcile.ts:20-30 |
| Replacement | Unkeyed arrays and non-plain objects are swapped wholesale. | src/merge.ts:38-49 |
| Immutability | Never mutates base; returns original reference if no change occurs. | test/laws.test.ts:119-126 |
Data Operations and Sentinels
Optimistic UI updates often require deleting fields or items. keyfold uses explicit sentinels to differentiate between "no change" and "deletion."
Field Deletion
To remove a field from an object, the DELETE symbol is used. In environments where symbols cannot be transmitted (like JSON over WebSockets), the DELETE_TOKEN ("@@keyfold/delete") can be enabled via the wireDeletes option.
The sequence illustrates how the DELETE sentinel triggers field removal during a merge.
Sources: src/sentinels.ts:2-5, src/merge.ts:88-94, README.md:103-112
Item Reconciliation in Lists
For keyed lists, reconciliation follows a specific lifecycle to maintain UI stability:
- Index Delta: Identify all items and tombstones (
$delete: true) in the incoming delta. - Scan Base: Iterate through the base list.
- Merge/Delete: If an item exists in both, merge them. If it has a tombstone, remove it.
- Append: Any items in the delta not present in the base are appended to the end of the list.
Sources: src/reconcile.ts:20-63, AGENTS.md:29-33
Integration Patterns
Optimistic Replacement
The "[]" suffix in path configuration allows for the "item-swap" idiom. This is useful when the UI wants to replace a whole item in a list upon identity match rather than performing a deep merge of the item's properties.
// Configuration for replacing matched items wholesale
const replaceItems = createMerger<State>({
keyBy: { "order.items": "id" },
replace: ["order.items[]"], // The '[]' addresses the items themselves
});
Sources: src/paths.ts:56-65, README.md:65-74
Identity Constraints
To ensure technical accuracy and prevent UI state corruption, identity fields must meet specific criteria:
- Stability: Identity values must not change.
- Uniqueness: Duplicate identities in a single list will cause a
KeyfoldMergeError. - Types: Must be strictly
stringornumber(excludingNaN).
Sources: src/reconcile.ts:109-138, README.md:54-58
Technical Summary
keyfold acts as a deterministic state reducer for optimistic UI. By enforcing structural sharing and identity-based reconciliation, it allows frontend applications to apply partial server updates (deltas) to local state trees safely. The system's O(delta) performance—where costs scale with the size of the update rather than the full state—makes it suitable for high-frequency UI updates, with the O(list) exception for touched keyed lists.
Sources: AGENTS.md:38-40, README.md:154-159, test/laws.test.ts:87-96