Skip to content

Commit

Permalink
refactor catch up
Browse files Browse the repository at this point in the history
Major refactoring in stripes-core between this branch's initial work and
the present lead to some discrepancies. The only change of note here, I
think, is the relocation of `<Suspense>` from ModuleRoutes down into
AppRoutes. It isn't clear to me why that was necessary or why it worked.
It was just a hunch that I tried ... and it worked.

Prior to that change, AppRoutes would get stuck in a render loop,
infinitely reloading (yes, even the memoized functions). I don't have a
good explanation for the bug or the fix.
  • Loading branch information
zburke committed Dec 4, 2024
1 parent f66ad62 commit 44bd6dd
Show file tree
Hide file tree
Showing 8 changed files with 165 additions and 170 deletions.
9 changes: 3 additions & 6 deletions bootstrap.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import 'core-js/stable';
import 'regenerator-runtime/runtime';

import React from 'react';
import { createRoot } from 'react-dom/client';

import App from './src/App';

export default function init() {
const container = document.getElementById('root');
const root = createRoot(container);
root.render(<App />);
}
const container = document.getElementById('root');
const root = createRoot(container);
root.render(<App />);
1 change: 0 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ export { supportedNumberingSystems } from './src/loginServices';
export { userLocaleConfig } from './src/loginServices';
export * from './src/consortiaServices';
export { default as queryLimit } from './src/queryLimit';
export { default as init } from './src/init';

/* localforage wrappers hide the session key */
export { getOkapiSession, getTokenExpiry, setTokenExpiry } from './src/loginServices';
Expand Down
63 changes: 33 additions & 30 deletions src/AppRoutes.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import React, { useMemo } from 'react';
import React, { useMemo, Suspense } from 'react';
import { Route } from 'react-router-dom';
import PropTypes from 'prop-types';

import { connectFor } from '@folio/stripes-connect';
import { LoadingView } from '@folio/stripes-components';

import { StripesContext } from './StripesContext';
import TitleManager from './components/TitleManager';
Expand Down Expand Up @@ -50,37 +51,39 @@ const AppRoutes = ({ modules, stripes }) => {
}, [modules.app, stripes]);

return cachedModules.map(({ ModuleComponent, connect, module, name, moduleStripes, stripes: propsStripes, displayName }) => (
<Route
path={module.route}
key={module.route}
render={props => {
const data = { displayName, name };
<Suspense fallback={<LoadingView />}>
<Route
path={module.route}
key={module.route}
render={props => {
const data = { displayName, name };

// allow SELECT_MODULE handlers to intervene
const handlerComponents = getEventHandlers(events.SELECT_MODULE, moduleStripes, modules.handler, data);
if (handlerComponents.length) {
return handlerComponents.map(Handler => (<Handler stripes={propsStripes} data={data} />));
}
// allow SELECT_MODULE handlers to intervene
const handlerComponents = getEventHandlers(events.SELECT_MODULE, moduleStripes, modules.handler, data);
if (handlerComponents.length) {
return handlerComponents.map(Handler => (<Handler stripes={propsStripes} data={data} />));
}

return (
<StripesContext.Provider value={moduleStripes}>
<ModuleHierarchyProvider module={module.module}>
<div id={`${name}-module-display`} data-module={module.module} data-version={module.version}>
<RouteErrorBoundary
escapeRoute={module.home ?? module.route}
moduleName={displayName}
stripes={moduleStripes}
>
<TitleManager page={displayName}>
<ModuleComponent {...props} connect={connect} stripes={moduleStripes} actAs="app" />
</TitleManager>
</RouteErrorBoundary>
</div>
</ModuleHierarchyProvider>
</StripesContext.Provider>
);
}}
/>
return (
<StripesContext.Provider value={moduleStripes}>
<ModuleHierarchyProvider module={module.module}>
<div id={`${name}-module-display`} data-module={module.module} data-version={module.version}>
<RouteErrorBoundary
escapeRoute={module.home ?? module.route}
moduleName={displayName}
stripes={moduleStripes}
>
<TitleManager page={displayName}>
<ModuleComponent {...props} connect={connect} stripes={moduleStripes} actAs="app" />
</TitleManager>
</RouteErrorBoundary>
</div>
</ModuleHierarchyProvider>
</StripesContext.Provider>
);
}}
/>
</Suspense>
));
};

Expand Down
6 changes: 1 addition & 5 deletions src/ModuleRoutes.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,7 @@ function ModuleRoutes({ stripes }) {
);
}

return (
<Suspense fallback={<LoadingView />}>
<AppRoutes modules={modules} stripes={stripes} />
</Suspense>
);
return <AppRoutes modules={modules} stripes={stripes} />;
}}
</ModulesContext.Consumer>
);
Expand Down
2 changes: 2 additions & 0 deletions src/Pluggable.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import React, { useMemo, Suspense } from 'react';
import PropTypes from 'prop-types';

import { Icon } from '@folio/stripes-components';

import { useModules } from './ModulesContext';
import { withStripes } from './StripesContext';
import { ModuleHierarchyProvider } from './components';
Expand Down
248 changes: 123 additions & 125 deletions src/RootWithIntl.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,131 +53,129 @@ const RootWithIntl = ({ stripes, token = '', isAuthenticated = false, disableAut
return (
<StripesContext.Provider value={connectedStripes}>
<CalloutContext.Provider value={callout}>
<RegistryLoader stripes={stripes}>
<ModuleTranslator>
<TitleManager>
<HotKeys
keyMap={connectedStripes.bindings}
noWrapper
>
<Provider store={connectedStripes.store}>
<Router history={history}>
{ isAuthenticated || token || disableAuth ?
<>
<MainContainer>
<AppCtxMenuProvider>
<MainNav stripes={connectedStripes} queryClient={queryClient} />
{typeof connectedStripes?.config?.staleBundleWarning === 'object' && <StaleBundleWarning />}
<HandlerManager
event={events.LOGIN}
stripes={connectedStripes}
/>
{ (typeof connectedStripes.okapi !== 'object' || connectedStripes.discovery.isFinished) && (
<ModuleContainer id="content">
<OverlayContainer />
{connectedStripes.config.useSecureTokens && <SessionEventContainer history={history} queryClient={queryClient} />}
<Switch>
<TitledRoute
name="home"
path="/"
key="root"
exact
component={<Front stripes={connectedStripes} />}
/>
<TitledRoute
name="ssoRedirect"
path="/sso-landing"
key="sso-landing"
component={<SSORedirect stripes={connectedStripes} />}
/>
<TitledRoute
name="oidcRedirect"
path="/oidc-landing"
key="oidc-landing"
component={<OIDCRedirect stripes={stripes} />}
/>
<TitledRoute
name="logoutTimeout"
path="/logout-timeout"
component={<Logout />}
/>
<TitledRoute
name="settings"
path="/settings"
component={<Settings stripes={connectedStripes} />}
/>
<TitledRoute
name="logout"
path="/logout"
component={<Logout />}
/>
<ModuleRoutes stripes={connectedStripes} />
</Switch>
</ModuleContainer>
)}
</AppCtxMenuProvider>
</MainContainer>
<Callout ref={setCalloutDomRef} />
</> :
<Switch>
{/* The ? after :token makes that part of the path optional, so that token may optionally
be passed in via URL parameter to avoid length restrictions */}
<TitledRoute
name="CreateResetPassword"
path="/reset-password/:token?"
component={<CreateResetPassword stripes={connectedStripes} />}
/>
<TitledRoute
name="ssoLanding"
exact
path="/sso-landing"
component={<CookiesProvider><SSOLanding stripes={connectedStripes} /></CookiesProvider>}
key="sso-landing"
/>
<TitledRoute
name="oidcLanding"
exact
path="/oidc-landing"
component={<CookiesProvider><OIDCLanding stripes={stripes} /></CookiesProvider>}
key="oidc-landing"
/>
<TitledRoute
name="forgotPassword"
path="/forgot-password"
component={<ForgotPasswordCtrl stripes={connectedStripes} />}
/>
<TitledRoute
name="forgotUsername"
path="/forgot-username"
component={<ForgotUserNameCtrl stripes={connectedStripes} />}
/>
<TitledRoute
name="checkEmail"
path="/check-email"
component={<CheckEmailStatusPage />}
/>
<TitledRoute
name="logout"
path="/logout"
component={<Logout />}
/>
<TitledRoute
name="logoutTimeout"
path="/logout-timeout"
component={<Logout />}
/>
<TitledRoute
name="login"
path="*"
component={<AuthnLogin stripes={connectedStripes} />}
/>
</Switch>
}
</Router>
</Provider>
</HotKeys>
</TitleManager>
</ModuleTranslator>
<RegistryLoader stripes={connectedStripes}>
<TitleManager>
<HotKeys
keyMap={connectedStripes.bindings}
noWrapper
>
<Provider store={connectedStripes.store}>
<Router history={history}>
{ isAuthenticated || token || disableAuth ?
<>
<MainContainer>
<AppCtxMenuProvider>
<MainNav stripes={connectedStripes} queryClient={queryClient} />
{typeof connectedStripes?.config?.staleBundleWarning === 'object' && <StaleBundleWarning />}
<HandlerManager
event={events.LOGIN}
stripes={connectedStripes}
/>
{ (typeof connectedStripes.okapi !== 'object' || connectedStripes.discovery.isFinished) && (
<ModuleContainer id="content">
<OverlayContainer />
{connectedStripes.config.useSecureTokens && <SessionEventContainer history={history} queryClient={queryClient} />}
<Switch>
<TitledRoute
name="home"
path="/"
key="root"
exact
component={<Front stripes={connectedStripes} />}
/>
<TitledRoute
name="ssoRedirect"
path="/sso-landing"
key="sso-landing"
component={<SSORedirect stripes={connectedStripes} />}
/>
<TitledRoute
name="oidcRedirect"
path="/oidc-landing"
key="oidc-landing"
component={<OIDCRedirect stripes={stripes} />}
/>
<TitledRoute
name="logoutTimeout"
path="/logout-timeout"
component={<Logout />}
/>
<TitledRoute
name="settings"
path="/settings"
component={<Settings stripes={connectedStripes} />}
/>
<TitledRoute
name="logout"
path="/logout"
component={<Logout />}
/>
<ModuleRoutes stripes={connectedStripes} />
</Switch>
</ModuleContainer>
)}
</AppCtxMenuProvider>
</MainContainer>
<Callout ref={setCalloutDomRef} />
</> :
<Switch>
{/* The ? after :token makes that part of the path optional, so that token may optionally
be passed in via URL parameter to avoid length restrictions */}
<TitledRoute
name="CreateResetPassword"
path="/reset-password/:token?"
component={<CreateResetPassword stripes={connectedStripes} />}
/>
<TitledRoute
name="ssoLanding"
exact
path="/sso-landing"
component={<CookiesProvider><SSOLanding stripes={connectedStripes} /></CookiesProvider>}
key="sso-landing"
/>
<TitledRoute
name="oidcLanding"
exact
path="/oidc-landing"
component={<CookiesProvider><OIDCLanding stripes={stripes} /></CookiesProvider>}
key="oidc-landing"
/>
<TitledRoute
name="forgotPassword"
path="/forgot-password"
component={<ForgotPasswordCtrl stripes={connectedStripes} />}
/>
<TitledRoute
name="forgotUsername"
path="/forgot-username"
component={<ForgotUserNameCtrl stripes={connectedStripes} />}
/>
<TitledRoute
name="checkEmail"
path="/check-email"
component={<CheckEmailStatusPage />}
/>
<TitledRoute
name="logout"
path="/logout"
component={<Logout />}
/>
<TitledRoute
name="logoutTimeout"
path="/logout-timeout"
component={<Logout />}
/>
<TitledRoute
name="login"
path="*"
component={<AuthnLogin stripes={connectedStripes} />}
/>
</Switch>
}
</Router>
</Provider>
</HotKeys>
</TitleManager>
</RegistryLoader>
</CalloutContext.Provider>
</StripesContext.Provider>
Expand Down
4 changes: 2 additions & 2 deletions src/components/About/WarningBanner.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ const WarningBanner = ({
<MessageBanner
type="warning"
show={!!missingModulesCount}
dismissable
dismissible
ref={bannerRef}
>
<Headline>{missingModulesMsg}</Headline>
Expand All @@ -61,7 +61,7 @@ const WarningBanner = ({
<MessageBanner
type="warning"
show={!!incompatibleModulesCount}
dismissable
dismissible
ref={bannerRef}
>
<Headline>{incompatibleModuleMsg}</Headline>
Expand Down
Loading

0 comments on commit 44bd6dd

Please sign in to comment.