diff --git a/docs/Admin.md b/docs/Admin.md index 968aa048127..2585ea4b135 100644 --- a/docs/Admin.md +++ b/docs/Admin.md @@ -482,7 +482,7 @@ See [Using React-Admin In A Sub Path](./Routing.md#using-react-admin-in-a-sub-pa ## `ready` -When you run an `` with no child ``, react-admin displays a "ready" screen: +When you run an `` with no child `` nor ``, react-admin displays a "ready" screen: ![Empty Admin](./img/tutorial_empty.png) diff --git a/packages/ra-core/src/core/useConfigureAdminRouterFromChildren.spec.tsx b/packages/ra-core/src/core/useConfigureAdminRouterFromChildren.spec.tsx index 0340275ceea..61e2572f9df 100644 --- a/packages/ra-core/src/core/useConfigureAdminRouterFromChildren.spec.tsx +++ b/packages/ra-core/src/core/useConfigureAdminRouterFromChildren.spec.tsx @@ -1,11 +1,14 @@ import * as React from 'react'; import { render, screen, waitFor } from '@testing-library/react'; import expect from 'expect'; +import { Route } from 'react-router-dom'; import { createMemoryHistory } from 'history'; + import { useResourceDefinitions } from './useResourceDefinitions'; import { CoreAdminContext } from './CoreAdminContext'; import { CoreAdminRoutes } from './CoreAdminRoutes'; import { Resource } from './Resource'; +import { CustomRoutes } from './CustomRoutes'; import { CoreLayoutProps } from '../types'; import { AuthProvider, ResourceProps } from '..'; @@ -31,6 +34,7 @@ const MyLayout = ({ children }: CoreLayoutProps) => ( ); const CatchAll = () =>
; const Loading = () => <>Loading; +const Ready = () => <>Ready; const TestedComponent = ({ role }) => { const history = createMemoryHistory(); @@ -185,6 +189,36 @@ const TestedComponentWithPermissions = () => { ); }; +const TestedComponentWithOnlyLazyCustomRoutes = ({ history }) => { + const [lazyRoutes, setLazyRoutes] = React.useState(null); + + React.useEffect(() => { + const timer = setTimeout( + () => + setLazyRoutes( + + Foo
} /> +
+ ), + 500 + ); + return () => clearTimeout(timer); + }, [setLazyRoutes]); + + return ( + + + {lazyRoutes} + + + ); +}; + const expectResource = (resource: string) => expect(screen.queryByText(`"name":"${resource}"`, { exact: false })); @@ -280,4 +314,14 @@ describe('useConfigureAdminRouterFromChildren', () => { expectResource('user').not.toBeNull(); expectResource('admin').toBeNull(); }); + it('should allow dynamically loaded custom routes without any resources', async () => { + const history = createMemoryHistory(); + render(); + expect(screen.queryByText('Ready')).not.toBeNull(); + + await new Promise(resolve => setTimeout(resolve, 1010)); + expect(screen.queryByText('Ready')).toBeNull(); + history.push('/foo'); + expect(screen.queryByText('Foo')).not.toBeNull(); + }); }); diff --git a/packages/ra-core/src/core/useConfigureAdminRouterFromChildren.tsx b/packages/ra-core/src/core/useConfigureAdminRouterFromChildren.tsx index 2ed39f7adf4..7734044dbba 100644 --- a/packages/ra-core/src/core/useConfigureAdminRouterFromChildren.tsx +++ b/packages/ra-core/src/core/useConfigureAdminRouterFromChildren.tsx @@ -129,7 +129,9 @@ const useRoutesAndResourcesFromChildren = ( setStatus( !!functionChild ? 'loading' - : newRoutesAndResources.resources.length > 0 + : newRoutesAndResources.resources.length > 0 || + newRoutesAndResources.customRoutesWithLayout.length > 0 || + newRoutesAndResources.customRoutesWithoutLayout.length > 0 ? 'ready' : 'empty' ); diff --git a/packages/ra-no-code/src/Admin.tsx b/packages/ra-no-code/src/Admin.tsx index e3cd8ed9142..2a7cef08030 100644 --- a/packages/ra-no-code/src/Admin.tsx +++ b/packages/ra-no-code/src/Admin.tsx @@ -12,7 +12,7 @@ import { ResourceConfigurationPage, ResourceConfigurationProvider, } from './ResourceConfiguration'; -import { Layout, Ready } from './ui'; +import { Layout } from './ui'; import { Route } from 'react-router'; import { useApplication } from './ApplicationContext'; @@ -43,7 +43,7 @@ const InnerAdmin = (props: AdminProps) => { const hasResources = !!resources && Object.keys(resources).length > 0; return ( - + ( - -); +export const Layout = (props: LayoutProps) => { + const [resources] = useResourcesConfiguration(); + const hasResources = !!resources && Object.keys(resources).length > 0; + + if (!hasResources) { + return ; + } + + return ; +};