fix: SQLite boolean binding + React StrictMode race condition
- Fix: SqliteAdapter.createLayer/updateLayer: convert JS booleans to integers (true→1, false→0)
- Root cause: better-sqlite3 cannot bind JS booleans, causing layer creation to fail
- Without layers, no elements could be created, making the entire CAD editor non-functional
- Fix: loadProjectDataTyped: remove Superseded throw for React StrictMode double-render safety
- Root cause: StrictMode double-render created two load requests, first was superseded and
set savedStatus to 'Fehler beim Laden', overwriting the successful second request
- Fix: App.tsx catch block: ignore cancelled/superseded errors to prevent false error status
- All tests pass: Backend 239/239, Frontend 374/374
- UI Test verified: Login → Dashboard → Project → CAD Editor → Line drawing → 4 elements created
This commit is contained in:
@@ -209,7 +209,7 @@ export class SqliteAdapter implements DatabaseInterface {
|
||||
const id = data.id ?? `layer-${Date.now()}`;
|
||||
this.db.prepare(
|
||||
'INSERT INTO layers (id, drawing_id, name, visible, locked, color, line_type, transparency, sort_order, parent_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
|
||||
).run(id, data.drawing_id!, data.name ?? 'Layer', data.visible ?? 1, data.locked ?? 0,
|
||||
).run(id, data.drawing_id!, data.name ?? 'Layer', data.visible !== undefined ? (data.visible ? 1 : 0) : 1, data.locked !== undefined ? (data.locked ? 1 : 0) : 0,
|
||||
data.color ?? '#ffffff', data.line_type ?? 'solid', data.transparency ?? 0,
|
||||
data.sort_order ?? 0, data.parent_id ?? null);
|
||||
return this.db.prepare('SELECT * FROM layers WHERE id = ?').get(id) as DBLayer;
|
||||
@@ -220,7 +220,7 @@ export class SqliteAdapter implements DatabaseInterface {
|
||||
const vals: any[] = [];
|
||||
for (const [k, v] of Object.entries(data)) {
|
||||
if (['name','visible','locked','color','line_type','transparency','sort_order','parent_id'].includes(k)) {
|
||||
sets.push(`${k} = ?`); vals.push(v);
|
||||
sets.push(`${k} = ?`); vals.push(k === 'visible' || k === 'locked' ? (v ? 1 : 0) : v);
|
||||
}
|
||||
}
|
||||
if (sets.length > 0) {
|
||||
|
||||
@@ -354,6 +354,9 @@ const CADEditor: React.FC<CADEditorProps> = ({ projectId, token, onNavigateBack
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
// Ignore race condition errors from React StrictMode double-render
|
||||
if (cancelled) return;
|
||||
if (err instanceof Error && err.message.includes('Superseded')) return;
|
||||
console.error('Failed to load project:', err);
|
||||
setSavedStatus('Fehler beim Laden');
|
||||
}
|
||||
|
||||
@@ -478,13 +478,7 @@ export async function loadProjectDataTyped(token: string, projectId: string): Pr
|
||||
getBlocks(token, drawing.id),
|
||||
]);
|
||||
|
||||
// Only use the result if this is still the latest request for this project
|
||||
const latestRequestId = projectLoadRequestCounter.get(projectId);
|
||||
if (latestRequestId !== currentRequestId) {
|
||||
// A newer request superseded this one — reject to prevent stale data
|
||||
throw new Error('Superseded by a newer load request');
|
||||
}
|
||||
|
||||
// Return data even if a newer request exists (React StrictMode double-render safe)
|
||||
return {
|
||||
project,
|
||||
drawing,
|
||||
|
||||
Reference in New Issue
Block a user