diff --git a/lib/components/sync-community-store-handler.react.js b/lib/components/sync-community-store-handler.react.js
new file mode 100644
--- /dev/null
+++ b/lib/components/sync-community-store-handler.react.js
@@ -0,0 +1,53 @@
+// @flow
+
+import * as React from 'react';
+
+import {
+ useFetchCommunityInfos,
+ fetchCommunityInfosActionTypes,
+} from '../actions/community-actions.js';
+import { isLoggedIn } from '../selectors/user-selectors.js';
+import { thinThreadTypes } from '../types/thread-types-enum.js';
+import { useDispatchActionPromise } from '../utils/redux-promise-utils.js';
+import { useSelector } from '../utils/redux-utils.js';
+
+function SyncCommunityStoreHandler(): React.Node {
+ const loggedIn = useSelector(isLoggedIn);
+ const threadInfos = useSelector(state => state.threadStore.threadInfos);
+ const communityInfos = useSelector(
+ state => state.communityStore.communityInfos,
+ );
+ const callFetchCommunityInfos = useFetchCommunityInfos();
+ const dispatchActionPromise = useDispatchActionPromise();
+
+ React.useEffect(() => {
+ if (!loggedIn) {
+ return;
+ }
+
+ const communityRootThreads = Object.values(threadInfos).filter(
+ thread => thread.type === thinThreadTypes.COMMUNITY_ROOT,
+ );
+
+ const missingCommunityInfos = communityRootThreads.some(
+ thread => !(thread.id in communityInfos),
+ );
+
+ if (missingCommunityInfos) {
+ void dispatchActionPromise(
+ fetchCommunityInfosActionTypes,
+ callFetchCommunityInfos(),
+ );
+ }
+ }, [
+ callFetchCommunityInfos,
+ communityInfos,
+ dispatchActionPromise,
+ loggedIn,
+ threadInfos,
+ ]);
+
+ return null;
+}
+
+export default SyncCommunityStoreHandler;
diff --git a/native/root.react.js b/native/root.react.js
--- a/native/root.react.js
+++ b/native/root.react.js
@@ -34,6 +34,7 @@
import PrekeysHandler from 'lib/components/prekeys-handler.react.js';
import { QRAuthProvider } from 'lib/components/qr-auth-provider.react.js';
import { StaffContextProvider } from 'lib/components/staff-provider.react.js';
+import SyncCommunityStoreHandler from 'lib/components/sync-community-store-handler.react.js';
import { UserIdentityCacheProvider } from 'lib/components/user-identity-cache.react.js';
import { DBOpsHandler } from 'lib/handlers/db-ops-handler.react.js';
import { HoldersHandler } from 'lib/handlers/holders-handler.react.js';
@@ -390,6 +391,7 @@
+
{navigation}
diff --git a/web/app.react.js b/web/app.react.js
--- a/web/app.react.js
+++ b/web/app.react.js
@@ -24,6 +24,7 @@
import PlatformDetailsSynchronizer from 'lib/components/platform-details-synchronizer.react.js';
import { QRAuthProvider } from 'lib/components/qr-auth-provider.react.js';
import { StaffContextProvider } from 'lib/components/staff-provider.react.js';
+import SyncCommunityStoreHandler from 'lib/components/sync-community-store-handler.react.js';
import { DBOpsHandler } from 'lib/handlers/db-ops-handler.react.js';
import { HoldersHandler } from 'lib/handlers/holders-handler.react.js';
import { TunnelbrokerDeviceTokenHandler } from 'lib/handlers/tunnelbroker-device-token-handler.react.js';
@@ -258,6 +259,7 @@
+
{content}