Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F32167448
D9141.1765052290.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
D9141.1765052290.diff
View Options
diff --git a/keyserver/src/responders/website-responders.js b/keyserver/src/responders/website-responders.js
--- a/keyserver/src/responders/website-responders.js
+++ b/keyserver/src/responders/website-responders.js
@@ -237,6 +237,7 @@
commServicesAccessToken: t.Nil,
inviteLinksStore: inviteLinksStoreValidator,
keyserverStore: keyserverStoreValidator,
+ initialStateLoaded: tBool(false),
});
async function websiteResponder(
@@ -603,6 +604,7 @@
commServicesAccessToken: null,
inviteLinksStore: inviteLinksStorePromise,
keyserverStore: keyserverStorePromise,
+ initialStateLoaded: false,
});
const validatedInitialReduxState = validateOutput(
viewer.platformDetails,
diff --git a/web/redux/initial-state-gate.js b/web/redux/initial-state-gate.js
new file mode 100644
--- /dev/null
+++ b/web/redux/initial-state-gate.js
@@ -0,0 +1,66 @@
+// @flow
+
+import * as React from 'react';
+import { useDispatch } from 'react-redux';
+import { PersistGate } from 'redux-persist/es/integration/react.js';
+import type { Persistor } from 'redux-persist/es/types';
+
+import { useServerCall } from 'lib/utils/action-utils.js';
+import { infoFromURL } from 'lib/utils/url-utils.js';
+
+import { getInitialReduxState, setInitialReduxState } from './action-types.js';
+import { useSelector } from './redux-utils.js';
+import Loading from '../loading.react.js';
+
+type Props = {
+ +persistor: Persistor,
+ +children: React.Node,
+};
+function InitialReduxStateGate(props: Props): React.Node {
+ const { children, persistor } = props;
+ const callGetInitialReduxState = useServerCall(getInitialReduxState);
+ const dispatch = useDispatch();
+
+ const [initError, setInitError] = React.useState<?Error>(null);
+ React.useEffect(() => {
+ if (initError) {
+ throw initError;
+ }
+ }, [initError]);
+
+ const isRehydrated = useSelector(state => !!state._persist?.rehydrated);
+ const prevIsRehydrated = React.useRef(false);
+ React.useEffect(() => {
+ if (!prevIsRehydrated.current && isRehydrated) {
+ prevIsRehydrated.current = isRehydrated;
+ (async () => {
+ try {
+ const urlInfo = infoFromURL(decodeURI(window.location.href));
+ const payload = await callGetInitialReduxState(urlInfo);
+ dispatch({ type: setInitialReduxState, payload });
+ } catch (err) {
+ setInitError(err);
+ }
+ })();
+ }
+ }, [callGetInitialReduxState, dispatch, isRehydrated]);
+
+ const initialStateLoaded = useSelector(state => state.initialStateLoaded);
+
+ const childFunction = React.useCallback(
+ // This argument is passed from `PersistGate`. It means that the state is
+ // rehydrated and we can start fetching the initial info.
+ bootstrapped => {
+ if (bootstrapped && initialStateLoaded) {
+ return children;
+ } else {
+ return <Loading />;
+ }
+ },
+ [children, initialStateLoaded],
+ );
+
+ return <PersistGate persistor={persistor}>{childFunction}</PersistGate>;
+}
+
+export default InitialReduxStateGate;
diff --git a/web/redux/redux-setup.js b/web/redux/redux-setup.js
--- a/web/redux/redux-setup.js
+++ b/web/redux/redux-setup.js
@@ -97,6 +97,7 @@
+commServicesAccessToken: ?string,
+inviteLinksStore: InviteLinksStore,
+keyserverStore: KeyserverStore,
+ +initialStateLoaded: boolean,
};
export type Action =
@@ -140,6 +141,7 @@
},
},
},
+ initialStateLoaded: true,
});
} else if (action.type === updateWindowDimensionsActionType) {
return validateState(oldState, {
diff --git a/web/root.js b/web/root.js
--- a/web/root.js
+++ b/web/root.js
@@ -7,7 +7,6 @@
import { createStore, applyMiddleware, type Store } from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension/logOnlyInProduction.js';
import { persistReducer, persistStore } from 'redux-persist';
-import { PersistGate } from 'redux-persist/es/integration/react.js';
import thunk from 'redux-thunk';
import { reduxLoggerMiddleware } from 'lib/utils/action-logger.js';
@@ -16,7 +15,7 @@
import { SQLiteDataHandler } from './database/sqlite-data-handler.js';
import { localforageConfig } from './database/utils/constants.js';
import ErrorBoundary from './error-boundary.react.js';
-import Loading from './loading.react.js';
+import InitialReduxStateGate from './redux/initial-state-gate.js';
import { persistConfig } from './redux/persist.js';
import { type AppState, type Action, reducer } from './redux/redux-setup.js';
import history from './router-history.js';
@@ -36,15 +35,15 @@
const RootProvider = (): React.Node => (
<Provider store={store}>
- <PersistGate persistor={persistor} loading={<Loading />}>
- <ErrorBoundary>
+ <ErrorBoundary>
+ <InitialReduxStateGate persistor={persistor}>
<Router history={history.getHistoryObject()}>
<Route path="*" component={App} />
</Router>
<Socket />
<SQLiteDataHandler />
- </ErrorBoundary>
- </PersistGate>
+ </InitialReduxStateGate>
+ </ErrorBoundary>
</Provider>
);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Dec 6, 8:18 PM (20 h, 58 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5840614
Default Alt Text
D9141.1765052290.diff (5 KB)
Attached To
Mode
D9141: [web] Use new intial redux state
Attached
Detach File
Event Timeline
Log In to Comment