Understanding Data Providers
A data provider is an object that implements methods for CRUD operations and data fetching. Refine uses these methods through data hooks to manage all server communication.Quick Start
@refinedev/simple-rest@refinedev/graphql@refinedev/supabase@refinedev/strapi-v4@refinedev/hasura@refinedev/appwrite@refinedev/nestjsx-crudimport { Refine } from "@refinedev/core";
import dataProvider from "@refinedev/simple-rest";
const App = () => (
<Refine
dataProvider={dataProvider("https://api.fake-rest.refine.dev")}
resources={[
{
name: "posts",
list: "/posts",
create: "/posts/create",
edit: "/posts/edit/:id",
show: "/posts/show/:id",
},
]}
>
{/* Your app */}
</Refine>
);
Using Data Hooks
Once configured, use Refine’s data hooks to interact with your API:Fetching Lists
Creating Records
Updating Records
Multiple Data Providers
You can use multiple data providers in a single application:Customizing Data Providers
Overriding Methods
Customize specific methods while keeping the rest:Using Meta for Custom Parameters
Pass custom parameters through themeta field:
Creating a Custom Data Provider
import { DataProvider } from "@refinedev/core";
import axios from "axios";
export const customDataProvider = (apiUrl: string): DataProvider => ({
getApiUrl: () => apiUrl,
// Implement required methods
getList: async ({ resource, pagination, sorters, filters }) => {
const url = `${apiUrl}/${resource}`;
// Build query parameters
const params = {
page: pagination?.currentPage || 1,
limit: pagination?.pageSize || 10,
};
const { data } = await axios.get(url, { params });
return {
data: data.items,
total: data.total,
};
},
getOne: async ({ resource, id }) => {
const { data } = await axios.get(`${apiUrl}/${resource}/${id}`);
return { data };
},
create: async ({ resource, variables }) => {
const { data } = await axios.post(`${apiUrl}/${resource}`, variables);
return { data };
},
update: async ({ resource, id, variables }) => {
const { data } = await axios.put(`${apiUrl}/${resource}/${id}`, variables);
return { data };
},
deleteOne: async ({ resource, id }) => {
const { data } = await axios.delete(`${apiUrl}/${resource}/${id}`);
return { data };
},
});
import { HttpError } from "@refinedev/core";
import axios from "axios";
const axiosInstance = axios.create();
axiosInstance.interceptors.response.use(
(response) => response,
(error) => {
const customError: HttpError = {
...error,
message: error.response?.data?.message || error.message,
statusCode: error.response?.status || 500,
};
return Promise.reject(customError);
}
);
getList: async ({ resource, pagination, sorters, filters }) => {
const query: any = {
page: pagination?.currentPage || 1,
limit: pagination?.pageSize || 10,
};
// Add sorting
if (sorters && sorters.length > 0) {
query.sort = sorters.map(s => `${s.field}:${s.order}`).join(",");
}
// Add filtering
if (filters) {
filters.forEach((filter) => {
if (filter.operator === "eq") {
query[filter.field] = filter.value;
}
});
}
const { data } = await axios.get(`${apiUrl}/${resource}`, {
params: query,
});
return {
data: data.items,
total: data.total,
};
},
Working with GraphQL
For GraphQL APIs, use the@refinedev/graphql package:
Best Practices
Use Type Safety
Handle Authentication
Cache Management
Refine uses TanStack Query for caching. Configure cache behavior:Common Patterns
Batch Operations
Implement bulk actions for better performance:Request Cancellation
Optimistic Updates
Troubleshooting
CORS Issues
If you encounter CORS errors:- Configure your backend to allow your frontend origin
- Use a proxy in development:
Debugging Requests
Add logging to your data provider:Next Steps
- Learn about Authentication
- Explore Form Handling
- Discover Real-time Updates