Fix React error

This commit is contained in:
Konstantin Wohlwend 2026-05-19 16:48:35 -07:00
parent 2dd233c6bc
commit bb901068cb
2 changed files with 11 additions and 5 deletions

View File

@ -499,3 +499,6 @@ A: Browser-only RDE endpoints should require RDE to be enabled, a local dashboar
## Q: How should development-environment project creation seed environment config?
A: Seed the normal initial environment config before marking the project as `isDevelopmentEnvironment=true`. Existing development-environment projects should continue to reject environment config override writes, but creation needs to populate defaults like RBAC permissions, password sign-in, and installed apps first; otherwise the write guard throws during setup/restart-deps.
## Q: What can cause React error #185 immediately on dashboard load?
A: React error #185 is a maximum update depth error. In the dashboard root, `useSyncExternalStore` snapshot getters must return cached referentially stable values. Returning a fresh object such as `{ status: "healthy" }` from `getSnapshot` on every call can make React think the external store changed on every render and loop immediately. Use module-level constants for stable snapshots.

View File

@ -23,6 +23,9 @@ type DevEnvironmentHealthSnapshot =
| { status: "checking" | "healthy" }
| { status: "unhealthy", restartCommand: string };
const CHECKING_DEV_ENVIRONMENT_HEALTH_SNAPSHOT: DevEnvironmentHealthSnapshot = { status: "checking" };
const HEALTHY_DEV_ENVIRONMENT_HEALTH_SNAPSHOT: DevEnvironmentHealthSnapshot = { status: "healthy" };
function isDevEnvironmentHealthResponse(value: unknown): value is { ok: boolean, restart_command: string } {
return (
value != null &&
@ -34,7 +37,7 @@ function isDevEnvironmentHealthResponse(value: unknown): value is { ok: boolean,
);
}
let devEnvironmentHealthSnapshot: DevEnvironmentHealthSnapshot = { status: "checking" };
let devEnvironmentHealthSnapshot: DevEnvironmentHealthSnapshot = CHECKING_DEV_ENVIRONMENT_HEALTH_SNAPSHOT;
const devEnvironmentHealthSubscribers = new Set<() => void>();
let devEnvironmentHealthTimer: ReturnType<typeof setInterval> | undefined;
let devEnvironmentHealthRequestSequence = 0;
@ -67,7 +70,7 @@ async function refreshDevEnvironmentHealth() {
}
setSnapshotIfCurrent(body.ok && response.ok
? { status: "healthy" }
? HEALTHY_DEV_ENVIRONMENT_HEALTH_SNAPSHOT
: { status: "unhealthy", restartCommand: body.restart_command });
} catch {
setSnapshotIfCurrent({
@ -80,7 +83,7 @@ async function refreshDevEnvironmentHealth() {
function subscribeDevEnvironmentHealth(callback: () => void) {
devEnvironmentHealthSubscribers.add(callback);
if (devEnvironmentHealthSubscribers.size === 1) {
setDevEnvironmentHealthSnapshot({ status: "checking" });
setDevEnvironmentHealthSnapshot(CHECKING_DEV_ENVIRONMENT_HEALTH_SNAPSHOT);
runAsynchronouslyWithAlert(refreshDevEnvironmentHealth());
devEnvironmentHealthTimer = setInterval(() => {
runAsynchronouslyWithAlert(refreshDevEnvironmentHealth());
@ -101,7 +104,7 @@ function getDevEnvironmentHealthSnapshot() {
}
function getServerDevEnvironmentHealthSnapshot(): DevEnvironmentHealthSnapshot {
return { status: "checking" };
return CHECKING_DEV_ENVIRONMENT_HEALTH_SNAPSHOT;
}
function subscribeHealthyDevEnvironment(_callback: () => void) {
@ -109,7 +112,7 @@ function subscribeHealthyDevEnvironment(_callback: () => void) {
}
function getHealthyDevEnvironmentSnapshot(): DevEnvironmentHealthSnapshot {
return { status: "healthy" };
return HEALTHY_DEV_ENVIRONMENT_HEALTH_SNAPSHOT;
}
function DevEnvironmentStoppedScreen(props: { restartCommand: string }) {