4.9 KiB
Project Learnings
This document captures important discoveries and gotchas encountered during OpenNoodl development.
React Hooks & EventDispatcher Integration (Dec 2025)
Problem: EventDispatcher Events Not Reaching React Hooks
Context: During TASK-004B (ComponentsPanel React migration), discovered that componentRenamed events from ProjectModel weren't triggering UI updates in React components.
Root Cause: Array reference instability causing useEffect to constantly re-subscribe/unsubscribe.
Discovery:
// ❌ BAD - Creates new array on every render
useEventListener(
ProjectModel.instance,
['componentAdded', 'componentRemoved', 'componentRenamed', 'rootNodeChanged'],
callback
);
// ✅ GOOD - Stable reference prevents re-subscription
const PROJECT_EVENTS = ['componentAdded', 'componentRemoved', 'componentRenamed', 'rootNodeChanged'];
useEventListener(ProjectModel.instance, PROJECT_EVENTS, callback);
Location:
packages/noodl-editor/src/editor/src/hooks/useEventListener.tspackages/noodl-editor/src/editor/src/views/panels/ComponentsPanelNew/hooks/useComponentsPanel.ts
Keywords: EventDispatcher, React hooks, useEffect, event subscription, array reference, re-render
Hot Reload Issues with React Hooks (Dec 2025)
Context: Code changes to React hooks not taking effect despite webpack hot reload.
Discovery: React hooks sometimes require a hard browser refresh or dev server restart to pick up changes, especially:
- Changes to
useEffectdependencies - Changes to custom hooks
- Changes to event subscription logic
Solution:
- Try hard refresh first:
Cmd+Shift+R(Mac) orCtrl+Shift+R(Windows) - If that fails, restart dev server: Stop (Ctrl+C) and
npm run dev - Clear browser cache if issues persist
Location: Affects all React hook development
Keywords: hot reload, React hooks, webpack, dev server, browser cache
Webpack 5 Persistent Caching Issues (Dec 2025)
Problem: Code Changes Not Loading Despite Dev Server Restart
Context: During TASK-004B, discovered that TypeScript source file changes weren't appearing in the running Electron app, even after multiple npm run dev restarts and cache clearing attempts.
Root Cause: Webpack 5 enables aggressive persistent caching by default:
- Primary cache:
packages/noodl-editor/node_modules/.cache - Electron cache:
~/Library/Application Support/Electron(macOS) - App cache:
~/Library/Application Support/OpenNoodl(macOS)
Discovery: Standard cache clearing may not be sufficient. The caches can persist across:
- Dev server restarts
- Electron restarts
- Multiple rapid development iterations
Solution:
# Kill any running processes first
killall node
killall Electron
# Clear all caches
cd packages/noodl-editor
rm -rf node_modules/.cache
rm -rf ~/Library/Application\ Support/Electron
rm -rf ~/Library/Application\ Support/OpenNoodl
# Start fresh
npm run dev
Best Practice: When debugging webpack/compilation issues, add module-level console.log markers at the TOP of your files to verify new code is loading:
// At top of file
console.log('🔥 MyModule.ts LOADED - Version 2.0');
If you don't see this marker in the console, your changes aren't loading - it's a cache/build issue, not a code issue.
Location: Affects all webpack-compiled code in packages/noodl-editor/
Keywords: webpack, cache, persistent caching, hot reload, dev server, Electron
React 19 useEffect with Array Dependencies (Dec 2025)
Problem: useEffect with Array Dependency Never Executes
Context: During TASK-004B, discovered that passing an array as a single dependency to useEffect prevents the effect from ever running.
Root Cause: React 19's Object.is() comparison for dependencies doesn't work correctly when an array is passed as a single dependency item.
Discovery:
// ❌ BROKEN - useEffect NEVER runs
const eventNames = ['event1', 'event2', 'event3'];
useEffect(() => {
console.log('This never prints!');
}, [dispatcher, eventNames]); // eventNames is an array reference
// ✅ CORRECT - Spread array into individual dependencies
const eventNames = ['event1', 'event2', 'event3'];
useEffect(() => {
console.log('This runs correctly');
}, [dispatcher, ...eventNames]); // Spreads to: [dispatcher, 'event1', 'event2', 'event3']
// ✅ ALSO CORRECT - Use stable array reference outside component
const EVENT_NAMES = ['event1', 'event2', 'event3']; // Outside component
function MyComponent() {
useEffect(() => {
// Works because EVENT_NAMES reference is stable
}, [dispatcher, ...EVENT_NAMES]);
}
Critical Rule: Never pass an array as a dependency to useEffect. Always spread it.
Location: Affects useEventListener hook and any custom hooks with array dependencies
Keywords: React 19, useEffect, dependencies, array, Object.is, spread operator, hook lifecycle