Skip to content

Commit 364bf82

Browse files
jkomorosclaude
andcommitted
Add boxing pattern and Frame mismatch error guidance
Added two important pattern discoveries to documentation: 1. **Boxing Pattern for Sorting Cell Arrays** (PATTERNS.md) - Wrap items in objects before sorting to preserve cell references - Pattern: box → sort → unbox - Maintains bidirectional binding through transformations - Use case: Sort by derived values (LLM results, calculations) - Real example: Shopping list sorted by aisle while keeping checkboxes reactive 2. **Frame Mismatch Error Guidance** (COMMON_ISSUES.md) - Explains what Frame mismatch errors are - When to worry vs when to ignore - Diagnostic steps - Key insight: Errors don't always mean broken functionality Both patterns discovered during shopping list aisle sorting work. Boxing approach suggested by Berni - works perfectly! 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent d297195 commit 364bf82

File tree

2 files changed

+74
-0
lines changed

2 files changed

+74
-0
lines changed

docs/common/COMMON_ISSUES.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,32 @@ export function DiffText({ from, to }) { // Won't compile!
236236
- Recipe files: Use JSX and compose with utility functions
237237
- Use `/// <cts-enable />` directive at the top of utility files
238238

239+
## Frame Mismatch Errors
240+
241+
### Issue: Console Shows "Error: Frame mismatch" During Pattern Execution
242+
243+
**Symptom**: Browser console displays `Error: Frame mismatch at popFrame(...)` errors during pattern interactions.
244+
245+
**Cause**: The reactive execution graph encountered unexpected frame state. Can happen with complex reactive dependencies, rapid state updates, or certain cell access patterns.
246+
247+
**When to worry:**
248+
- ❌ Feature actually broken or not working
249+
- ❌ Errors continuously flood console (hundreds per second)
250+
- ❌ Pattern crashes or becomes unresponsive
251+
252+
**When it's okay:**
253+
- ✅ Isolated errors that don't continuously repeat
254+
- ✅ Feature works correctly despite the errors
255+
- ✅ Errors occur during interaction but functionality is fine
256+
257+
**Action**:
258+
1. Test if your feature actually works
259+
2. If feature works: Errors can often be ignored
260+
3. If feature broken: Check for closure issues or simplify dependencies
261+
4. If persistent and problematic: Report to framework team
262+
263+
**Example**: Store mapper pattern showed Frame mismatch on every interaction but all features worked correctly.
264+
239265
## Transaction Conflicts and Retry Storms
240266

241267
If you see `ConflictError` messages in console, this is normal - the system retries transactions automatically. These warnings don't indicate a problem unless they occur continuously (retry storm).

docs/common/PATTERNS.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -607,6 +607,54 @@ const activeItems = derive(items, (list) => list.filter(item => !item.done));
607607
{activeItems.map(...)}
608608
```
609609
610+
**Issue: Sorting cell arrays while preserving reactivity**
611+
612+
When you need to sort items based on derived values (like LLM results) while maintaining cell references for bidirectional binding, use the **boxing pattern**:
613+
614+
```typescript
615+
// ❌ BROKEN - Sorting derived array loses cell references
616+
const sortedItems = derive(itemsWithAisles, (assignments) => {
617+
return assignments.slice().sort((a, b) => compare(a.aisle, b.aisle));
618+
});
619+
620+
{sortedItems.map(({ item }) => (
621+
<ct-checkbox $checked={item.done} /> // ✗ Doesn't work - items are read-only
622+
))}
623+
624+
// ✅ CORRECT - Boxing pattern preserves cell references
625+
// 1. Box: Wrap items in objects
626+
const boxedItems = itemsWithAisles.map(assignment => ({ assignment }));
627+
628+
// 2. Sort: Perform sort on boxed items
629+
const sortedBoxedItems = derive(boxedItems, (boxed) => {
630+
return boxed.slice().sort((a, b) => {
631+
// Access properties via .assignment prefix
632+
const aValue = a.assignment.aisle;
633+
const bValue = b.assignment.aisle;
634+
return aValue.localeCompare(bValue);
635+
});
636+
});
637+
638+
// 3. Unbox: Map over sorted items, extract original cell reference
639+
{sortedBoxedItems.map(({ assignment }) => (
640+
<ct-checkbox $checked={assignment.item.done} /> // ✓ Works! Cell preserved
641+
))}
642+
```
643+
644+
**Why this works:**
645+
- Boxing wraps the cell reference in a plain object `{ assignment }`
646+
- Sorting rearranges the wrapper objects, not the cells themselves
647+
- The original cell reference (`assignment.item`) remains intact
648+
- Bidirectional binding works because we're accessing the original cell
649+
650+
**When to use:**
651+
- Sorting items by derived/computed values (LLM results, calculations)
652+
- Reordering while maintaining reactivity
653+
- Any transformation that needs to preserve cell references
654+
655+
**Real-world example:**
656+
Shopping list sorted by grocery store aisle (from LLM categorization) while keeping checkboxes reactive.
657+
610658
**Issue: Can't access variable from outer map**
611659
612660
```typescript

0 commit comments

Comments
 (0)