Skip to main content
Version: 3.xx.xx

Router Provider

refine needs some router functions to create resource pages, navigate, etc. This provider allows you to use the router library you want.

A router provider must include the following methods:

const routerProvider = {
useHistory: () => {
push: (...args) => any,
replace: (...args) => any,
goBack: (...args) => any,
},
useLocation: () => {
pathname: string,
search: string,
},
useParams: <Params extends { [K in keyof Params]?: string } = {}>() => Params,
Prompt: React.FC<PromptProps*>,
Link: React.FC<any>,
RouterComponent?: React.FC<any>,
};

*: Too see <PromptProps>

info

refine includes many out-of-the-box router providers to use in your projects like

tip

We do not recommend creating this provider unless you do not need any customization on the router. Instead, you can use Next.js Router for your Next.js app and React Router V6, React Router V5 or React Location for your react app.

Usage

To activate router provider in refine, we have to pass the routerProvider to the <Refine /> component.

App.tsx
import { Refine } from "@pankod/refine-core";
import routerProvider from "@pankod/refine-react-router-v6";

const App: React.FC = () => {
return <Refine routerProvider={routerProvider} />;
};

Creating a router provider

The routerProvider methods refine expects are exactly the same as React Router V6 methods.

To understand how to create a routerProvider, let's examine how the React Router V6, React Router V5, React Location and Next.js Router libraries provided by refine create a routerProvider.

useHistory

refine uses push, replace, and goBack functions of useHistory for navigation.

routerProvider.ts
import { IRouterProvider } from "@pankod/refine-core";

const routerProvider: IRouterProvider = {
...
useHistory: () => {
const navigate = useNavigate();

return {
push: navigate,
replace: (path: string) => {
navigate(path, { replace: true });
},
goBack: () => {
navigate(-1);
},
};
},

...
};

useLocation

refine uses the pathname to find the location of the user and search to find the query string.

routerProvider.ts
import { IRouterProvider } from "@pankod/refine-core";
import { useLocation } from "react-router-dom";

const routerProvider: IRouterProvider = {
...
useLocation,
...
};

useParams

refine uses useParams to use action name, record id, etc. found in the route.

routerProvider.ts
import { IRouterProvider } from "@pankod/refine-core";
import { useParams } from "react-router-dom";

const routerProvider: IRouterProvider = {
...
useParams,
...
};

Prompt

refine uses <Prompt> to display the alert when warnWhenUnsavedChanges is true.

Prompt.tsx
import { useEffect, useContext } from "react";
import { UNSAFE_NavigationContext as NavigationContext } from "react-router-dom";
import type { History } from "history";

import type { PromptProps } from "@pankod/refine-core";

export const Prompt: React.FC<PromptProps> = ({
message,
when,
setWarnWhen,
}) => {
const navigator = useContext(NavigationContext).navigator as History;

useEffect(() => {
if (!when) return;

const unblock = navigator.block((transition: any) => {
if (window.confirm(message)) {
setWarnWhen?.(false);
unblock();
transition.retry();
} else {
navigator.location.pathname = window.location.pathname;
}
});
return unblock;
}, [when, location, message]);

return null;
};
routerProvider.ts
import { IRouterProvider } from "@pankod/refine-core";

import { Prompt } from "./prompt";

const routerProvider: IRouterProvider = {
...
Prompt,
...
};

refine uses <Link> for navigation.

routerProvider.ts
import { IRouterProvider } from "@pankod/refine-core";
import { Link } from "react-router-dom";

const routerProvider: IRouterProvider = {
...
Link,
...
};

routes

routes allow us to create custom pages in your react apps that have different paths than those defined by resources.

Refer to the Custom Pages documentation for detailed information.

info

Since Nextjs and Remix has a file system based router built on the page concept, you can create your custom pages under the pages folder you don't need routes property.

RouterComponent

It creates the navigation routes of the refine app and determines how the components will be rendered on which paths.

In general, we can list what it does as follows:

  • It creates create, edit, list, show pages with paths according to the resources' own name.
  • Allows rendering of custom routes passed to routerProviders as properties.
  • Different routes render when the user is authenticated and not.
info

RouterComponent is required for refine React apps but not required for Next.js and Remix apps.

Since Next.js and Remix has a folder base route structure, it is used by exporting the <NextRouteComponent> or <RemixRouteComponent> from the created page.


Refer to the React Router V6's <RouterComponent> for detailed usage information.
Refer to the React Router V5's <RouterComponent> for detailed usage information.
Refer to the React Location's <RouterComponent> for detailed usage information.
Refer to the Next.js Router's <NextRouteComponent> for detailed usage information. Refer to the Next.js Router's <RemixRouteComponent> for detailed usage information.

Serving the application from a subdirectory

If you want to serve from a subdirectory in your refine react app. You can use basename property of <BrowserRouter>.

The <RouterComponent> in the react-router-v6 package passes all its properties to the <BrowserRouter> component. Therefore, a <BrowserRouter> property that we will give to the <RouterComponent> is passed to the <BrowserRouter> that wraps our application.

In the example below you can see how to serve the application in a subdirectory.

src/App.tsx
import { Refine } from "@pankod/refine-core";
import routerProvider from "@pankod/refine-react-router-v6";
import dataProvider from "@pankod/refine-simple-rest";
import "@pankod/refine/dist/styles.min.css";

import { PostList, PostCreate, PostEdit, PostShow } from "pages/posts";

const API_URL = "https://api.fake-rest.refine.dev";

const { RouterComponent } = routerProvider;

const CustomRouterComponent = () => <RouterComponent basename="/admin" />;

const App: React.FC = () => {
return (
<Refine
routerProvider={{
...routerProvider,
RouterComponent: CustomRouterComponent,
}}
dataProvider={dataProvider(API_URL)}
resources={[
{
name: "posts",
list: PostList,
create: PostCreate,
edit: PostEdit,
show: PostShow,
},
]}
/>
);
};

export default App;

Now you can access our application at www.domain.com/admin.

Changing the initial route of your application

refine initially shows the DashboardPage component from <Refine/> props, if there are no DashboardPage component is present, refine redirects to the first list page in the resources array. You can change this behavior by passing initialRoute value to the RouterComponents of the router providers.

RouterComponent property in the routerProvider from @pankod/refine-react-router-v6 checks for the initialRoute property in its context. If it is present, it will redirect to the given route. By default routerProvider is using BrowserRouterComponent but both HashRouterComponent and MemoryRouterComponent also supports initialRoute property.

In the example below, BrowserRouterComponent is used and the initial route is set to /users.

src/App.tsx
import { Refine } from "@pankod/refine-core";
import routerProvider, {
BrowserRouterComponent,
} from "@pankod/refine-react-router-v6";
import dataProvider from "@pankod/refine-simple-rest";
import "@pankod/refine/dist/styles.min.css";

import { PostList, PostCreate, PostEdit, PostShow } from "pages/posts";
import { UserList, UserShow } from "pages/users";

const API_URL = "https://api.fake-rest.refine.dev";

const App: React.FC = () => {
return (
<Refine
routerProvider={{
...routerProvider,
RouterComponent: BrowserRouterComponent.bind({
initialRoute: "/users",
}),
}}
dataProvider={dataProvider(API_URL)}
resources={[
{
name: "posts",
list: PostList,
create: PostCreate,
edit: PostEdit,
show: PostShow,
},
{
name: "users",
list: UserList,
show: UserShow,
},
]}
/>
);
};

export default App;