Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix customRoutes aren't used when the resources are empty #6112

Merged
merged 1 commit into from
Apr 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions examples/simple/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint react/jsx-key: off */
import * as React from 'react';
import { Admin, Resource } from 'react-admin'; // eslint-disable-line import/no-unresolved
import { Admin, Resource, CustomRoute } from 'react-admin'; // eslint-disable-line import/no-unresolved
import { render } from 'react-dom';
import { Route } from 'react-router-dom';

Expand All @@ -23,7 +23,7 @@ render(
title="Example Admin"
layout={Layout}
customRoutes={[
<Route
<Route<CustomRoute>
exact
path="/custom"
component={props => <CustomRouteNoLayout {...props} />}
Expand Down
52 changes: 47 additions & 5 deletions packages/ra-core/src/core/CoreAdminRouter.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,10 @@ describe('<CoreAdminRouter>', () => {
getPermissions: jest.fn().mockResolvedValue(''),
};

const { getByText } = renderWithRedux(
const { queryByText } = renderWithRedux(
<AuthContext.Provider value={authProvider}>
<Router history={history}>
<CoreAdminRouter {...defaultProps} layout={Layout}>
<CoreAdminRouter layout={Layout}>
{() => [
<Resource
key="posts"
Expand All @@ -104,12 +104,54 @@ describe('<CoreAdminRouter>', () => {
);
// Timeout needed because of the authProvider call
await waitFor(() => {
expect(getByText('Layout')).not.toBeNull();
expect(queryByText('Layout')).not.toBeNull();
});
history.push('/posts');
expect(getByText('PostList')).not.toBeNull();
expect(queryByText('PostList')).not.toBeNull();
history.push('/comments');
expect(getByText('CommentList')).not.toBeNull();
expect(queryByText('CommentList')).not.toBeNull();
});

it('should return loading while the resources are not resolved', async () => {
const history = createMemoryHistory();
const authProvider = {
login: jest.fn().mockResolvedValue(''),
logout: jest.fn().mockResolvedValue(''),
checkAuth: jest.fn().mockResolvedValue(''),
checkError: jest.fn().mockResolvedValue(''),
getPermissions: jest.fn().mockResolvedValue(''),
};
const Loading = () => <>Loading</>;
const Custom = () => <>Custom</>;

const { queryByText } = renderWithRedux(
<AuthContext.Provider value={authProvider}>
<Router history={history}>
<CoreAdminRouter
{...defaultProps}
layout={Layout}
loading={Loading}
customRoutes={[
<Route
key="foo"
noLayout
path="/foo"
component={Custom}
/>,
]}
>
{() => new Promise(() => {})}
</CoreAdminRouter>
</Router>
</AuthContext.Provider>
);
// Timeout needed because of the authProvider call
await new Promise(resolve => setTimeout(resolve, 1010));
history.push('/posts');
expect(queryByText('Loading')).not.toBeNull();
history.push('/foo');
expect(queryByText('Loading')).toBeNull();
expect(queryByText('Custom')).not.toBeNull();
});
});

Expand Down
49 changes: 30 additions & 19 deletions packages/ra-core/src/core/CoreAdminRouter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,33 +107,43 @@ const CoreAdminRouter: FunctionComponent<AdminRouterProps> = props => {
loading: LoadingPage,
logout,
menu,
ready,
ready: Ready,
theme,
title,
} = props;

if (
(typeof children !== 'function' && !children) ||
(Array.isArray(children) && children.length === 0)
) {
return createElement(ready);
if (typeof children !== 'function' && !children) {
return <Ready />;
}

if (
typeof children === 'function' &&
(!computedChildren || computedChildren.length === 0)
(typeof children === 'function' &&
(!computedChildren || computedChildren.length === 0)) ||
(Array.isArray(children) && children.length === 0)
) {
if (oneSecondHasPassed) {
return (
<Route
path="/"
key="loading"
render={() => <LoadingPage theme={theme} />}
/>
);
} else {
return null;
}
return (
<Switch>
{customRoutes
.filter(route => route.props.noLayout)
.map((route, key) =>
cloneElement(route, {
key,
render: routeProps =>
renderCustomRoutesWithoutLayout(
route,
routeProps
),
component: undefined,
})
)}
{oneSecondHasPassed && (
<Route
key="loading"
render={() => <LoadingPage theme={theme} />}
/>
)}
</Switch>
);
}

const childrenToRender = (typeof children === 'function'
Expand Down Expand Up @@ -167,6 +177,7 @@ const CoreAdminRouter: FunctionComponent<AdminRouterProps> = props => {
route,
routeProps
),
component: undefined,
})
)}
<Route
Expand Down
1 change: 1 addition & 0 deletions packages/ra-core/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,7 @@ export type AdminChildren = RenderResourcesFunction | ReactNode;

export interface CustomRoute extends RouteProps {
noLayout?: boolean;
[key: string]: any;
}

export type CustomRoutes = Array<ReactElement<CustomRoute>>;
Expand Down