fix(use-default-subplebbits): prevent state updates after unmount

This commit is contained in:
plebeius
2025-11-04 14:59:22 +01:00
parent c808f0ca21
commit e548198d0e
+126 -73
View File
@@ -95,50 +95,67 @@ export const useDefaultSubplebbits = () => {
return; return;
} }
let isMounted = true;
(async () => { (async () => {
try { try {
// Check localStorage first // Check localStorage first
const cachedData = getFromLocalStorage(); const cachedData = getFromLocalStorage();
if (cachedData) { if (cachedData) {
cacheSubplebbits = cachedData.subplebbits; cacheSubplebbits = cachedData.subplebbits;
setState({ if (isMounted) {
subplebbits: cachedData.subplebbits,
loading: false,
error: null,
});
// Still try to fetch fresh data in background (don't await)
fetchMultisubData().then((data) => {
cacheSubplebbits = data.subplebbits;
setState({ setState({
subplebbits: data.subplebbits, subplebbits: cachedData.subplebbits,
loading: false, loading: false,
error: null, error: null,
}); });
}); }
// Still try to fetch fresh data in background (don't await)
fetchMultisubData()
.then((data) => {
if (isMounted) {
cacheSubplebbits = data.subplebbits;
setState({
subplebbits: data.subplebbits,
loading: false,
error: null,
});
}
})
.catch((e) => {
console.warn('Background fetch failed:', e);
});
return; return;
} }
// No cache, fetch fresh data // No cache, fetch fresh data
const multisub = await fetchMultisubData(); const multisub = await fetchMultisubData();
cacheSubplebbits = multisub.subplebbits; if (isMounted) {
cacheSubplebbits = multisub.subplebbits;
setState({ setState({
subplebbits: multisub.subplebbits, subplebbits: multisub.subplebbits,
loading: false, loading: false,
error: null, error: null,
}); });
}
} catch (e) { } catch (e) {
console.warn('Failed to load subplebbits:', e); console.warn('Failed to load subplebbits:', e);
// Fallback to vendored data // Fallback to vendored data
const fallbackData = defaultSubplebbitsData as MultisubData; const fallbackData = defaultSubplebbitsData as MultisubData;
cacheSubplebbits = fallbackData.subplebbits; if (isMounted) {
setState({ cacheSubplebbits = fallbackData.subplebbits;
subplebbits: fallbackData.subplebbits, setState({
loading: false, subplebbits: fallbackData.subplebbits,
error: null, loading: false,
}); error: null,
});
}
} }
})(); })();
return () => {
isMounted = false;
};
}, []); }, []);
// To maintain backward compatibility, return the subplebbits array directly // To maintain backward compatibility, return the subplebbits array directly
@@ -162,50 +179,67 @@ export const useDefaultSubplebbitsState = () => {
return; return;
} }
let isMounted = true;
(async () => { (async () => {
try { try {
// Check localStorage first // Check localStorage first
const cachedData = getFromLocalStorage(); const cachedData = getFromLocalStorage();
if (cachedData) { if (cachedData) {
cacheSubplebbits = cachedData.subplebbits; cacheSubplebbits = cachedData.subplebbits;
setState({ if (isMounted) {
subplebbits: cachedData.subplebbits,
loading: false,
error: null,
});
// Still try to fetch fresh data in background (don't await)
fetchMultisubData().then((data) => {
cacheSubplebbits = data.subplebbits;
setState({ setState({
subplebbits: data.subplebbits, subplebbits: cachedData.subplebbits,
loading: false, loading: false,
error: null, error: null,
}); });
}); }
// Still try to fetch fresh data in background (don't await)
fetchMultisubData()
.then((data) => {
if (isMounted) {
cacheSubplebbits = data.subplebbits;
setState({
subplebbits: data.subplebbits,
loading: false,
error: null,
});
}
})
.catch((e) => {
console.warn('Background fetch failed:', e);
});
return; return;
} }
// No cache, fetch fresh data // No cache, fetch fresh data
const multisub = await fetchMultisubData(); const multisub = await fetchMultisubData();
cacheSubplebbits = multisub.subplebbits; if (isMounted) {
cacheSubplebbits = multisub.subplebbits;
setState({ setState({
subplebbits: multisub.subplebbits, subplebbits: multisub.subplebbits,
loading: false, loading: false,
error: null, error: null,
}); });
}
} catch (e) { } catch (e) {
console.warn('Failed to load subplebbits:', e); console.warn('Failed to load subplebbits:', e);
// Fallback to vendored data // Fallback to vendored data
const fallbackData = defaultSubplebbitsData as MultisubData; const fallbackData = defaultSubplebbitsData as MultisubData;
cacheSubplebbits = fallbackData.subplebbits; if (isMounted) {
setState({ cacheSubplebbits = fallbackData.subplebbits;
subplebbits: fallbackData.subplebbits, setState({
loading: false, subplebbits: fallbackData.subplebbits,
error: null, loading: false,
}); error: null,
});
}
} }
})(); })();
return () => {
isMounted = false;
};
}, []); }, []);
return state; return state;
@@ -223,6 +257,9 @@ export const useMultisubMetadata = () => {
if (cacheMetadata) { if (cacheMetadata) {
return; return;
} }
let isMounted = true;
(async () => { (async () => {
try { try {
// Check localStorage first // Check localStorage first
@@ -235,45 +272,61 @@ export const useMultisubMetadata = () => {
updatedAt: cachedData.updatedAt, updatedAt: cachedData.updatedAt,
}; };
cacheMetadata = metadata; cacheMetadata = metadata;
setMetadata(metadata); if (isMounted) {
setMetadata(metadata);
}
// Still try to fetch fresh data in background (don't await) // Still try to fetch fresh data in background (don't await)
fetchMultisubData().then((data) => { fetchMultisubData()
const freshMetadata: MultisubMetadata = { .then((data) => {
title: data.title, if (isMounted) {
description: data.description, const freshMetadata: MultisubMetadata = {
createdAt: data.createdAt, title: data.title,
updatedAt: data.updatedAt, description: data.description,
}; createdAt: data.createdAt,
cacheMetadata = freshMetadata; updatedAt: data.updatedAt,
setMetadata(freshMetadata); };
}); cacheMetadata = freshMetadata;
setMetadata(freshMetadata);
}
})
.catch((e) => {
console.warn('Background metadata fetch failed:', e);
});
return; return;
} }
// No cache, fetch fresh data // No cache, fetch fresh data
const multisub = await fetchMultisubData(); const multisub = await fetchMultisubData();
const metadata: MultisubMetadata = { if (isMounted) {
title: multisub.title, const metadata: MultisubMetadata = {
description: multisub.description, title: multisub.title,
createdAt: multisub.createdAt, description: multisub.description,
updatedAt: multisub.updatedAt, createdAt: multisub.createdAt,
}; updatedAt: multisub.updatedAt,
cacheMetadata = metadata; };
setMetadata(metadata); cacheMetadata = metadata;
setMetadata(metadata);
}
} catch (e) { } catch (e) {
console.warn('Failed to load metadata, using vendored fallback:', e); console.warn('Failed to load metadata, using vendored fallback:', e);
// Fallback to vendored data // Fallback to vendored data
const fallbackData = defaultSubplebbitsData as MultisubData; const fallbackData = defaultSubplebbitsData as MultisubData;
const metadata: MultisubMetadata = { if (isMounted) {
title: fallbackData.title, const metadata: MultisubMetadata = {
description: fallbackData.description, title: fallbackData.title,
createdAt: fallbackData.createdAt, description: fallbackData.description,
updatedAt: fallbackData.updatedAt, createdAt: fallbackData.createdAt,
}; updatedAt: fallbackData.updatedAt,
cacheMetadata = metadata; };
setMetadata(metadata); cacheMetadata = metadata;
setMetadata(metadata);
}
} }
})(); })();
return () => {
isMounted = false;
};
}, []); }, []);
return cacheMetadata || metadata; return cacheMetadata || metadata;