commit ad25cd31f829eb012a1f8cfa0e89065d00738ccd
parent fa01e5b4dc7a230d858cebaa0fda87bc28bacc19
Author: Sebastian <sebasjm@taler-systems.com>
Date: Wed, 22 Jul 2026 15:59:05 -0300
doUpdate is using stale data from anastasisState, using callback form in setAnastasisStateInternal to use an up-to-date previous state
Diffstat:
1 file changed, 55 insertions(+), 36 deletions(-)
diff --git a/packages/anastasis-webui/src/hooks/use-anastasis-reducer.ts b/packages/anastasis-webui/src/hooks/use-anastasis-reducer.ts
@@ -186,6 +186,48 @@ function getStateFromStorage(): any {
return state ?? undefined;
}
+async function tryUpdateProviders(
+ prevState: AnastasisState,
+ newState: AnastasisState,
+): Promise<undefined | AnastasisState> {
+ const reducerState = newState.reducerState;
+ if (
+ reducerState?.reducer_type !== "backup" &&
+ reducerState?.reducer_type !== "recovery"
+ ) {
+ return undefined;
+ }
+ const provMap = reducerState.authentication_providers;
+ if (!provMap) {
+ return undefined;
+ }
+ const doUpdate = async (): Promise<undefined | AnastasisState> => {
+ const updates = await completeProviderStatus(provMap);
+ if (Object.keys(updates).length === 0) {
+ return;
+ }
+ const rs2 = reducerState;
+ if (rs2.reducer_type !== "backup" && rs2.reducer_type !== "recovery") {
+ return;
+ }
+ const updated: AnastasisState = {
+ ...prevState,
+ reducerState: {
+ ...rs2,
+ authentication_providers: {
+ ...rs2.authentication_providers,
+ ...updates,
+ },
+ },
+ };
+ return updated;
+ };
+ return doUpdate().catch((e) => {
+ console.log("ERROR doUpdate", e);
+ return undefined;
+ });
+}
+
export function useAnastasisReducer(): AnastasisReducerApi {
const [anastasisState, setAnastasisStateInternal] = useState<AnastasisState>(
() => ({
@@ -206,44 +248,21 @@ export function useAnastasisReducer(): AnastasisReducerApi {
} catch (e) {
console.log("ERROR setAnastasisState", e);
}
- setAnastasisStateInternal(newState);
-
- const tryUpdateProviders = () => {
- const reducerState = newState.reducerState;
- if (
- reducerState?.reducer_type !== "backup" &&
- reducerState?.reducer_type !== "recovery"
- ) {
- return;
- }
- const provMap = reducerState.authentication_providers;
- if (!provMap) {
- return;
- }
- const doUpdate = async () => {
- const updates = await completeProviderStatus(provMap);
- if (Object.keys(updates).length === 0) {
- return;
- }
- const rs2 = reducerState;
- if (rs2.reducer_type !== "backup" && rs2.reducer_type !== "recovery") {
- return;
+ setAnastasisStateInternal(prevState => {
+ tryUpdateProviders(prevState, newState).then(result => {
+ if (result) {
+ // FIXME
+ // there is a missing clear loop cut
+ // the will end because completeProviderStatus returns an
+ // empty list after contacting all providers, but is not clear
+ // and fragile
+ setAnastasisState(result)
}
- setAnastasisState({
- ...anastasisState,
- reducerState: {
- ...rs2,
- authentication_providers: {
- ...rs2.authentication_providers,
- ...updates,
- },
- },
- });
- };
- doUpdate().catch((e) => console.log("ERROR doUpdate", e));
- };
+ })
+ return newState
+ });
- tryUpdateProviders();
+ ;
};
async function doTransition(action: string, args: any): Promise<void> {