UX 870 remove core stat from mobx#2220
Conversation
Migrated supported-features from MobX to Zustand: - Replaced @computed decorators with Zustand getters - Converted observable featureErrors array to Zustand state - Migrated FeatureErrorCheck component to use Zustand hook - Maintained backwards compatibility via Features singleton Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
|
The latest Buf updates on your PR. Results from workflow Buf CI / validate (pull_request).
|
|
@jvorcak is this ready for review? looks like a lot of changes |
|
@claude review |
|
Claude finished @jvorcak's task in 9m 11s —— View job PR Review: UX-870 Remove MobX from Core State
SummaryThis is a substantial refactoring that migrates core state from MobX to Zustand, converting 🔴 Critical Issues1. The original "click OK to clear error, click OK again to retry" UX flow is broken. The check // PROBLEM: currentUserState is captured unconditionally before the error check
updateState?.((prev) => {
currentUserState = prev.userState; // <-- always set (non-null while modal is visible)
if (prev.result?.error) {
return { ...prev, result: null };
}
return prev;
});
if (!currentUserState) { // <-- this is NEVER true
return;
}
// Always falls through to call onOk, even when we just cleared an errorThe fix would need to track separately whether an error was cleared, e.g. using a local boolean flag. Fix this → 🟠 Major Issues2. The 3. The old // Call once on initialization
updateSidebarItems();
// If routes can change dynamically, you can subscribe to relevant state changes
// For now, we just call it once since routes are staticThis means if 4. const checkUserData = () => {
if (api.userData) {
api.refreshSupportedEndpoints();
api.listLicenses();
} else {
setTimeout(checkUserData, 100); // <-- infinite loop until userData arrives
}
};If authentication fails or the user data never arrives, this loop runs forever. The original 🟡 Moderate Issues5. // Before (used response secretId):
const createSecretResponse = yield api.updateSecret(...);
property.value = secret.getSecretString(key, createSecretResponse?.secretId);
// After (uses pre-update id):
await api.updateSecret(this.clusterName, secret.id, secret.serialized);
property.value = secret.getSecretString(key, secret.id); // secret.id not refreshed from responseIf the 6. get topicSettings() {
try {
// ...
throw new Error('reaction for "currentTopicName" was supposed to create topicDetail settings container');
} catch (error) {
// In test environments, stores might not be properly initialized
return createTopicDetailsSettings(''); // silently returns default
}
},The broad 7. The new const filteredData = useMemo(() => {
return source.filter((item) => isFilterMatch(filterText, item));
}, [source, filterText, isFilterMatch]);But in 🔵 Minor / Design Notes8. The module-level closure variable 9. The 10. Setting ✅ Positive Notes
|
| title: v.title, | ||
| to: v.linkTo, | ||
| })); | ||
| useUIStateStore.subscribe((state) => { |
There was a problem hiding this comment.
Let's double check breadcrumbs are properly set now with this logic change, it was a problem in the past when navigating between pages
There was a problem hiding this comment.
I think we have e2e tests for this on some pages already, but I'll check
LoginPage reads loginError through the legacy uiState proxy but is wrapped in observer() which only tracks MobX observables. After PR #2220 migrated loginError to Zustand, the component stopped re-rendering when loginError changed to null, leaving the modal permanently stuck open. Subscribe to loginError via useUIStateStore so the component properly re-renders when the error is dismissed.
) * frontend: fix login error modal not closing after MobX removal LoginPage reads loginError through the legacy uiState proxy but is wrapped in observer() which only tracks MobX observables. After PR #2220 migrated loginError to Zustand, the component stopped re-rendering when loginError changed to null, leaving the modal permanently stuck open. Subscribe to loginError via useUIStateStore so the component properly re-renders when the error is dismissed. * frontend: fix feature flags not updating after MobX observer removal Move endpointCompatibility into the Zustand supported-features store so feature flags recompute when backend data arrives. Components using useSupportedFeaturesStore selectors now re-render reactively, fixing ACL schema registry buttons staying disabled and shadow link card never appearing. Also silence console errors for SecretService and MCPServerService endpoints not yet returned by the backend. * frontend: fix flaky connector lifecycle test in CI Wait for connector deletion to propagate before recreating, and use Playwright's built-in retry helpers instead of manual retry loops.
No description provided.