<Refine>
<Refine>
component is the entry point of a refine app. It is where the highest level of configuration of the app occurs.
dataProvider
and routerProvider
are required to bootstrap the app. After adding them, resources
can be added as property.
import { Refine } from "@refinedev/core";
import dataProvider from "@refinedev/simple-rest";
const API_URL = "https://api.fake-rest.refine.dev";
const App: React.FC = () => {
return (
<Refine
dataProvider={dataProvider(API_URL)}
resources={[
{
name: "posts",
list: "/posts",
},
]}
/>
);
};
export default App;
dataProvider
A dataProvider
is the place where a refine app communicates with an API.
Data providers also act as adapters for refine, making it possible for it to consume different API's and data services.
A dataProvider
makes HTTP requests and returns response data back using predefined methods.
Refer to the Data Provider documentation for detailed information. →
To activate multiple data provider in refine, we have to pass the default key with dataProvider
for the default data provider and we can pass other data providers with any key to the <Refine />
component.
import { Refine } from "@refinedev/core";
import {
default as defaultDataProvider,
default as exampleDataProvider,
} from "./dataProvider";
const App: React.FC = () => {
return (
<Refine
dataProvider={{
default: defaultDataProvider,
example: exampleDataProvider,
}}
/>
);
};
routerProvider
refine provides a simple interface from the routerProvider
prop to infer the resource from route, pass, parse and sync the query parameters and handle navigation operations. This provider and its properties are optional but it is recommended to use it to get the most out of refine. Bindings to pass to the routerProvider
prop are provided for the following libraries:
- React Router via
@refinedev/react-router-v6
- Next.js via
@refinedev/nextjs-router
- Remix via
@refinedev/remix-router
It's also possible to create a custom router bindings for your routing needs.
Refer to the Router Provider documentation for detailed information. →
In prior versions from v4 of refine, routerProvider
had a different interface and it was required. This is no longer the case and routerProvider
is optional. If you want to keep using the legacy router provider, you can use the legacyRouterProvider
prop instead.
resources
resources
is the main building block of a refine app. A resource represents an entity in an endpoint in the API (e.g. https://api.fake-rest.refine.dev/posts). It serves as a bridge between the data from the API and the pages in the app, allowing pages to interact with the data from the API.
Here's an app that consumes the https://api.fake-rest.refine.dev/posts endpoint as a resource to list multiple items, edit or create an item and show a single item.
Routes for the action pages that are for interacting with the CRUD API operations are passed as a resource element to resources
.
import { Refine } from "@refinedev/core";
import dataProvider from "@refinedev/json-server";
const API_URL = "https://api.fake-rest.refine.dev";
const App: React.FC = () => {
return (
<Refine
dataProvider={dataProvider(API_URL)}
resources={[
{
name: "posts",
list: "/posts", // Means that the list action of this resource will be available at /posts in your app
create: "/posts/create", // Means that the create action of this resource will be available at /posts/create in your app
edit: "/posts/edit/:id", // Means that the edit action of this resource will be available at /posts/edit/:id in your app
show: "/posts/show/:id", // Means that the show action of this resource will be available at /posts/show/:id in your app
},
]}
/>
);
};
export default App;
You can use useResource hook to get the current active resource by the route or you can pass the name
or the identifier
of a resource to the useResource
hook to get the resource object.
name
A string value that identifies a resource in the API. Interacting with the data in a resource will be done using an endpoint determined by the name
:
https://api.fake-rest.refine.dev/posts
https://api.fake-rest.refine.dev/posts/1
identifier
The identifier
value serves as the main matching key for a resource. It allows you to effectively differentiate between multiple resources that share the same name
.
There are scenarios where you may have multiple resources with the same name
but different meta
values. For instance, you might want a posts
resource utilizing the default data provider and another posts
resource utilizing the "typicode" data provider. In this case, you can use the identifier
to differentiate between them.
import { Refine } from "@refinedev/core";
<Refine
...
dataProvider={{
default: defaultDataProvider,
typicode: typicodeDataProvider,
}}
resources={[
{
name: "posts",
identifier: "posts",
meta: {
foo: "bar",
},
},
{
name: "posts",
identifier: "featured-posts",
meta: {
foo: "baz",
filter: {
featured: true,
},
dataProviderName: "typicode",
},
},
]}
>
...
</Refine>;
As you can see in the example above, we have two resources with the same name
but different identifier
values. Also, both resources have different meta
values. Using the identifier
, we can differentiate between the two resources like so:
import { useTable } from "@refinedev/core";
useTable({
resource: "featured-posts",
});
const typicodeDataProvider = {
//...
getList: async ({ resource, meta }) => {
console.log(resource); // "posts"
console.log(meta); // { foo: "baz", filter: { featured: true } }
},
//...
};
list
The list path of the resource. The value assigned to the list
will be treated as the list
action path for the resource and the navigation operations will be performed on this path.
You can also pass a component to this property. In this case the default value for the path will be used, which is the /${name}
.
There's also a third option, which is to pass an object with the component
and path
properties. This allows you to customize the path of the list action.
Passing a component or an object to the action will only take effect if the RefineRoutes component from one of the Router Packages is used in the app to render the routes.
When using the legacy router provider, only the component values will be used. Custom paths are not supported.
create
The create path of the resource. The value assigned to the create
will be treated as the create
action path for the resource and the navigation operations will be performed on this path.
You can also pass a component to this property. In this case the default value for the path will be used, which is the /${name}/create
.
There's also a third option, which is to pass an object with the component
and path
properties. This allows you to customize the path of the list action.
Passing a component or an object to the action will only take effect if the RefineRoutes component from one of the Router Packages is used in the app to render the routes.
When using the legacy router provider, only the component values will be used. Custom paths are not supported.
edit
The edit path of the resource. The value assigned to the edit
will be treated as the edit
action path for the resource and the navigation operations will be performed on this path.
You can also pass a component to this property. In this case the default value for the path will be used, which is the /${name}/edit/:id
.
There's also a third option, which is to pass an object with the component
and path
properties. This allows you to customize the path of the list action.
Passing a component or an object to the action will only take effect if the RefineRoutes component from one of the Router Packages is used in the app to render the routes.
When using the legacy router provider, only the component values will be used. Custom paths are not supported.
show
The show path of the resource. The value assigned to the show
will be treated as the show
action path for the resource and the navigation operations will be performed on this path.
You can also pass a component to this property. In this case the default value for the path will be used, which is the /${name}/show/:id
.
There's also a third option, which is to pass an object with the component
and path
properties. This allows you to customize the path of the list action.
Passing a component or an object to the action will only take effect if the RefineRoutes component from one of the Router Packages is used in the app to render the routes.
When using the legacy router provider, only the component values will be used. Custom paths are not supported.
Additional parameters can also be used in the paths for the actions of the resources. Paths like /:authorId/posts/:id/details
are also valid and supported. When these actions are used in the navigation helpers, the existing parameters from the URL and the meta
property of these functions will be used to determine the additional parameters when composing the path.
meta
Menu item name and route on clicking can be customized.
<Refine
...
resources={[
{
...
meta: { label: "custom", route: "/custom" }
},
]}
/>
label
Name to show in the menu. The plural form of the resource name is shown by default.
icon
An icon element can be passed as properties for the icon in the menu.
<Refine
...
resources={[
{
...
meta: {
icon: <CustomIcon />
}
},
]}
/>
canDelete
This value will be passed to all CRUD pages defined as the resources
element.
refine's <Edit> component uses canDelete
value to whether show delete button in the edit form or not.
parent
You can set this value if you want to nest your resource into another resource. Usually this value represents the name of the parent resource but you can also pass a custom string. In this case, it will still be interpreted as a parent resource.
This value is used by the useMenu
and useBreadcrumb
hooks.
<Refine
/* ... */
resources={[
{
name: "parent",
},
{
name: "child",
meta: {
parent: "parent",
},
},
]}
/>
dataProviderName
Default data provider name to use for the resource. If not specified, the default data provider will be used.
hide
Can be used to hide a resource
in Sider
. This resource is also filtered in the useMenu
hook.
route
route
This property is deprecated and only works with the legacy routers. When using the new routing system, please define the paths by the actions of the resource.
Custom route name for the resource.
You can also pass any type of property into the meta
object. This property you pass can be received from the useResource
authProvider
authProvider
handles authentication logic like login, logout flow, and checking user credentials. It is an object with methods that refine uses when necessary.
Refer to the Auth Provider documentation for detailed information. →
i18nProvider
The i18nProvider
property lets you add i18n support to your app. Making you able to use any i18n framework.
Refer to i18n documentation for detailed information. →
accessControlProvider
accessControlProvider
is the entry point for implementing access control for refine apps.
Refer to access control documentation for detailed information. →
liveProvider
refine lets you add Realtime support to your app via liveProvider
. It can be used to update and show data in Realtime throughout your app.
Refer to live provider documentation for detailed information. →
notificationProvider
notificationProvider
handles notification logic. It is an object with methods that refine uses when necessary.
Refer to the Notification Provider documentation for detailed information. →
options
options
is used to configure the app.
disableServerSideValidation
When the dataProvider
returns rejected promise with errors
field, the useForm
hook will set the errors
state with the errors
returned from the dataProvider
.
Refer to server-side validation documentation for detailed information. →
To disable this behavior, you can set the disableServerSideValidation
option to true
.
import { Refine } from "@refinedev/core";
const App: React.FC = () => {
return (
<Refine
// ...
options={{
disableServerSideValidation: true,
}}
>
// ...
</Refine>
);
};
breadcrumb
Customize or disable the breadcrumb. By default it uses the Breadcrumb component from respective package.
The value set in individual CRUD components (ANTD, Mantine, Material UI) will override the value set with breadcrumb
.
Refer to the Breadcrumb docs for further information. →
import { Breadcrumb } from "antd";
OR
import { Breadcrumb } from "@refinedev/mantine";
OR
import { Breadcrumb } from "@refinedev/mui";
OR
import { Breadcrumb } from "my-custom-breadcrumb";
const App: React.FC = () => {
return (
<Refine
...
options={{
breadcrumb: (
<div
style={{
padding: "3px 6px",
border: "2px dashed cornflowerblue",
}}
>
<Breadcrumb />
</div>
),
}}
/>
);
};
To disable the breadcrumb
const App: React.FC = () => {
return (
<Refine
...
options={{
breadcrumb: false,
}}
/>
);
};
mutationMode
mutationMode
determines which mode the mutations run with. (e.g. useUpdate, useDelete).
const App: React.FC = () => {
return (
<Refine
...
options={{ mutationMode: "optimistic" }}
/>
);
};
pessimistic
: The mutation runs immediately. Redirection and UI updates are executed after the mutation returns successfully. This is the default setting.
optimistic
: The mutation is applied locally, and redirection and UI updates are executed immediately as if the mutation is successful. If the mutation returns with an error, UI updates accordingly.
undoable
: The mutation is applied locally, and redirection and UI updates are executed immediately as if the mutation is successful. Waits for a customizable amount of timeout before mutation is applied. During the timeout, mutation can be canceled from the notification with the ?undo? button. UI will revert accordingly.
Refer to the Mutation Mode docs for further information. →
undoableTimeout
The duration of the timeout period in undoable mode is shown in milliseconds. Mutations can be canceled during this period. This period can also be set on the supported data hooks.
The value set in hooks will override the value set with undoableTimeout
.
undoableTimeout
has a default value of 5000
.
const App: React.FC = () => {
return (
<Refine
...
options={{ mutationMode: "undoable", undoableTimeout: 3500 }}
/>
);
};
syncWithLocation
List query parameter values can be edited manually by typing directly in the URL.
syncWithLocation
's default value is false
, so you need to set it to true
to activate the feature.
Form hooks like useDrawerForm
and useModalForm
also have a syncWithLocation
property but the value of this option has no effect on these hooks. You'll still need to set the syncWithLocation
property in hooks to true
to activate this feature.
When syncWithLocation
is active, the URL on the listing page shows query parameters like those shown below:
/posts?current=1&pageSize=8&sort[]=createdAt&order[]=desc
Users can change the current page, items count per page, and sort and filter parameters.
warnWhenUnsavedChanges
When you have unsaved changes and try to leave the current page, refine shows a confirmation modal box.
warnWhenUnsavedChanges
's default value is false
, so you need to set it to true
to activate the feature.
This feature also requires UnsavedChangesNotifier
component to be mounted. You can import this component from your router package.
liveMode
liveMode
controls whether to update data automatically or not, with auto
and manual
respectively if a related live event is recieved. The off
value can be used to avoid creating a subscription all together.
For more information, refer to the live provider documentation →
disableTelemetry
refine implements a simple and transparent telemetry module for collecting usage statistics defined in a very limited scope. This telemetry module is used to improve the refine experience. You can disable this by setting disableTelemetry
to true
.
For more information, refer to the refine telemetry documentation →
redirect
By default, refine redirects to the list
page of the resource after a successful form mutation. To change this behaviour based on the form action, set redirect
as follows:
const App: React.FC = () => {
return (
<Refine
...
options={{
redirect: {
afterCreate: "show",
afterClone: "edit",
afterEdit: false,
},
}}
/>
);
};
When the redirect
option is set to false
, no redirect is performed after a successful form mutation.
If you don't have a show page and you redirect to the show page, the user will be redirected to the list page. Also, in the undoable
and optimistic
mutation modes, redirect happens before the mutation succeeds. Therefore, if there is no data in the query cache, the user will be redirected to the list page.
reactQuery
clientConfig
Config for React Query client that refine uses.
refine uses some defaults that apply to all queries:
{
refetchOnWindowFocus: false,
keepPreviousData: true,
}
const App: React.FC = () => (
<Refine
...
options={{
reactQuery: {
clientConfig: {
defaultOptions: {
queries: {
staleTime: Infinity,
},
},
},
},
}}
/>
);
Also, you can implement your own QueryClient.
import { QueryClient } from "@tanstack/react-query";
const queryClient = new QueryClient();
const App: React.FC = () => (
<Refine
...
options={{
reactQuery: {
clientConfig: queryClient
},
}}
/>
);
For more information, refer to the QueryClient documentation →
devtoolConfig
devtoolConfig
React Query Devtools are removed from the @refinedev/core
and this prop is no longer supported for the configuration of the devtools. You can use the @tanstack/react-query-devtools
in your app directly to use the devtools. For more information, please check out FAQ - How to use React Query Devtools with refine?
Config for customizing the React Query Devtools. If you want to disable the Devtools, set devtoolConfig
to false
.
refine uses some defaults that apply to react-query devtool:
{
initialIsOpen: false,
position: "bottom-right"
}
const App: React.FC = () => (
<Refine
...
// highlight-start
options={{
reactQuery: {
devtoolConfig: {
initialIsOpen: true,
position: "bottom-left",
},
},
}}
// highlight-end
/>
);
For more information, refer to the Devtools documentation →
textTransformers
The textTransformers
option in refine is used to transform the resource name displayed on the user interface (UI). By default, if you define a resource named posts
, refine will display it as Posts
. Similarly, when you delete a record, notification messages will be shown as Post deleted successfully.
.
You have the flexibility to customize these messages by using the textTransformers
option. For instance, if you wish to disable any transformation, you can set the textTransformers
option as shown in the example below:
const App: React.FC = () => (
<Refine
// ...
options={{
textTransformers: {
humanize: (text) => text,
plural: (text) => text,
singular: (text) => text,
},
}}
/>
);
humanize
The function converts the resource name to a more human-readable format. The default value uses the humanize-string
library.
plural
The function converts the resource name to its plural form. The default value uses the pluralize
library.
singular
The function converts the resource name to its singular form. The default value uses the pluralize
library.
overtime
If you want loading overtime for the request, you can use the overtime
object. It is useful when you want to show a loading indicator when the request takes too long.
const App: React.FC = () => (
<Refine
...
options={{
overtime: {
interval: 1000, // default value is 1000
onInterval: (elapsedInterval, context) => {
console.log(elapsedInterval, context);
},
}}
/>
);
interval
The interval value in milliseconds. The default value is 1000
.
onInterval
The callback function that will be called on every interval. The default value is undefined
.
The callback function receives two parameters:
elapsedInterval
: The elapsed interval in milliseconds.context
:
Description | Type |
---|---|
resource | IResourceItem | undefined |
resourceName | string | undefined |
id | BaseKey |
action | undefined | "list" | "create" | "edit" | "show" | "clone" |
useNewQueryKeys
With @refinedev/core
's v4.35.0
, refine introduced new query and mutation keys which are more structured and easy to construct. These keys are used in all data, auth, access control and audit log queries and mutations.
By default, refine uses the legacy keys for backward compatibility and in the future versions it will switch to using the new query keys. You can easily switch to using new keys by setting useNewQueryKeys
to true
.
onLiveEvent
Callback to handle all live events.
For more information, refer to the live provider documentation →
catchAll
catchAll
LoginPage
only works with the legacy routing system. It will be removed in the next major release. Please create a catch all route to handle this when using the new routing system.
When the app is navigated to a non-existent route, refine shows a default error page. A custom error component can be used for this error page by passing the customized component to the catchAll
property:
const CustomErrorPage = <div>Page not found</div>;
const App: React.FC = () => {
return (
<Refine
...
catchAll={CustomErrorPage}
/>
);
};
LoginPage
LoginPage
LoginPage
only works with the legacy routing system. It will be removed in the next major release. Please create a route for the login page when using the new routing system.
refine has a default login page form which is served on the /login
route when the authProvider
configuration is provided.
Custom login component can be passed to the LoginPage
property.
const CustomLoginPage = () => <div> Custom Login Page </div>;
const App: React.FC = () => (
<Refine
...
LoginPage={CustomLoginPage}
/>
);
DashboardPage
DashboardPage
DashboardPage
only works with the legacy routing system. It will be removed in the next major release. Please create a route for the root page when using the new routing system.
A custom dashboard page can be passed to the DashboardPage
prop which is accessible on the root route.
The dashboard item will appear at the top of the sider menu. If DashboardPage
is not given, the first resource of resources
will be shown.
const CustomDashboardPage = () => <div> Custom Dashboard Page </div>;
const App: React.FC = () => (
<Refine
...
DashboardPage={CustomDashboardPage}
/>
);
ReadyPage
ReadyPage
ReadyPage
only works with the legacy routing system. Now you can start using refine without any resources defined.
refine shows a default ready page on the root route when no resources
is passed to the <Refine>
.
Custom ready page component can be set by passing to the ReadyPage
property?.
const CustomReadyPage = () => <div> Custom Ready Page </div>;
const App: React.FC = () => (
<Refine
...
ReadyPage={CustomReadyPage}
/>
);
Sider
Sider
Sider
only works with the legacy routing system and the Layout
prop. Please pass the Sider
property to the Layout
component when using the new routing system.
The default sidebar can be customized by using refine hooks and passing custom components to the Sider
property.
refine uses Ant Design Sider component by default.
For more information, refer to the
useMenu
hook documentation →
Footer
Footer
Footer
only works with the legacy routing system and the Layout
prop. Please pass the Footer
property to the Layout
component when using the new routing system.
The default app footer can be customized by passing the Footer
property.
const CustomFooter = () => <div>Custom Footer</div>;
const App: React.FC = () => (
<Refine
...
Footer={CustomFooter}
/>
);
Header
Header
Header
only works with the legacy routing system and the Layout
prop. Please pass the Header
property to the Layout
component when using the new routing system.
The default app header can be customized by passing the Header
property.
const CustomHeader = () => <div>Custom Header</div>;
const App: React.FC = () => (
<Refine
...
Header={CustomHeader}
/>
);
Layout
Layout
Layout
only works with the legacy routing system and will be removed in the next major release. You can continue using the Layout
component by wrapping it to the components you want to render.
The default layout can be customized by passing the Layout
property.
refine uses Ant Design Layout components by default.
Layout property will receive individual layout components as property.
const App: React.FC = () => (
<Refine
...
Layout={({ children, Sider, Footer, Header, OffLayoutArea }) => (
<AntdLayout style={{ minHeight: "100vh", flexDirection: "row" }}>
{Sider && <Sider />}
<AntdLayout>
{Header && <Header />}
<AntdLayout.Content>
<div style={{ padding: 24, minHeight: 360 }}>
{children}
</div>
</AntdLayout.Content>
{Footer && <Footer />}
</AntdLayout>
{OffLayoutArea && <OffLayoutArea />}
</AntdLayout>
)}
/>
);
A completely custom layout can also be implemented instead of the refine's default Ant Design based layout like below.
const App: React.FC = () => (
<Refine
...
Layout={({ children }) => (
<div style={{ display: "flex", flexDirection: "column" }}>
<div>Custom Layout</div>
<div>{children}</div>
</div>
)}
/>
);
children` will be what is passed as a component for the route in a resource(list, edit..) or a custom route.
For more information, refer to the Custom Layout documentation →
OffLayoutArea
OffLayoutArea
OffLayoutArea
only works with the legacy routing system and the Layout
prop. Please pass the OffLayoutArea
property to the Layout
component when using the new routing system.
The component wanted to be placed out of the app layout structure can be set by passing to the OffLayoutArea
prop.
import { Refine } from "@refinedev/core";
const App: React.FC = () => (
<Refine
...
OffLayoutArea={() => <div>Some elements to place outside the layout</div>}
/>
);
Title
Title
Title
only works with the legacy routing system and the Layout
prop. Please pass the Title
property to the Layout
component when using the new routing system.
The app title can be set by passing the Title
property.
const CustomTitle = ({ collapsed }) => (
<div>{collapsed ? "Collapsed Title" : "Full Title"}</div>
);
const App: React.FC = () => (
<Refine
...
Title={CustomTitle}
/>
);
API Reference
Properties
dataProvider
routerProvider
resources
name
identifier
list
create
edit
show
meta
label
icon
canDelete
parent
dataProviderName
hide
route
authProvider
i18nProvider
accessControlProvider
liveProvider
notificationProvider
options
disableServerSideValidation
breadcrumb
mutationMode
undoableTimeout
syncWithLocation
warnWhenUnsavedChanges
liveMode
disableTelemetry
redirect
reactQuery
clientConfig
devtoolConfig
textTransformers
humanize
plural
singular
overtime
interval
onInterval
useNewQueryKeys
onLiveEvent
catchAll
LoginPage
DashboardPage
ReadyPage
Sider
Footer
Header
Layout
OffLayoutArea
Title
- API Reference
- Properties