diff --git a/docs/code-standards.md b/docs/code-standards.md index 14059628..66a0bb51 100644 --- a/docs/code-standards.md +++ b/docs/code-standards.md @@ -1,6 +1,6 @@ # CCS Code Standards -Last Updated: 2025-12-19 +Last Updated: 2025-12-21 Code standards, modularization patterns, and conventions for the CCS codebase. @@ -377,6 +377,92 @@ export function ComponentName({ id, onSave }: Props) { --- +## Input State Persistence Patterns + +When building forms and editors that allow users to make changes, follow these patterns to prevent data loss. + +### Pattern 1: Key-Based Remounting + +**Use when**: Component has complex local state that should reset on prop changes. + +```typescript +// Parent component + +``` + +**Why**: Without `key`, React reuses the component instance. Local `useState` values persist even when props change, causing stale data bugs. + +### Pattern 2: Unsaved Changes Confirmation + +**Use when**: User might navigate away while editing. + +```typescript +// Parent tracks dirty state +const [editorHasChanges, setEditorHasChanges] = useState(false); +const [pendingSwitch, setPendingSwitch] = useState(null); + +// Child notifies parent of dirty state +useEffect(() => { + onHasChangesUpdate?.(computedHasChanges); +}, [computedHasChanges, onHasChangesUpdate]); + +// Intercept navigation +const handleSelect = (id: string) => { + if (editorHasChanges && currentId !== id) { + setPendingSwitch(id); // Show confirmation dialog + } else { + setCurrentId(id); + } +}; +``` + +**Flow**: +1. Child computes `hasChanges` from local state vs saved data +2. Child notifies parent via callback +3. Parent intercepts navigation when dirty +4. Show confirmation dialog: "Discard & Switch" or "Cancel" +5. On confirm: reset dirty state, then switch + +### Pattern 3: Auto-Save with Visual Feedback + +**Use when**: Simple inputs that should save immediately. + +```typescript +const [saved, setSaved] = useState(false); + +const handleBlur = async () => { + if (value !== savedValue) { + await saveToBackend(value); + setSaved(true); + setTimeout(() => setSaved(false), 2000); + } +}; + +return ( +
+ + {saved && ( + + Saved + + )} +
+); +``` + +**When to use which**: +| Scenario | Pattern | +|----------|---------| +| Complex multi-field editor | Pattern 2 (confirmation dialog) | +| Simple single input | Pattern 3 (auto-save + feedback) | +| List item selection | Pattern 1 (key-based remount) + Pattern 2 | + +--- + ## Quality Gates ### Pre-Commit Sequence