Frappe React SDK
The `frappe-react-sdk` is a JavaScript library providing a collection of React hooks designed to simplify interaction with a Frappe Framework backend. It offers abstractions for common tasks such as user authentication (cookie-based or token-based), comprehensive database operations (fetching single documents, lists, counts, creating, updating, and deleting records), file uploads with progress tracking, and generic API calls to whitelisted backend functions. The current stable version is `1.14.0`. The library demonstrates an active release cadence, with updates typically every few weeks addressing bug fixes, dependency updates, and feature enhancements. Under the hood, it leverages `frappe-js-sdk` for Frappe API communication and `SWR` for efficient data fetching, caching, and automatic revalidation, providing a fast and reactive UI experience by default.
Common errors
-
Failed to load resource: net::ERR_CONNECTION_REFUSED
cause The Frappe server URL is incorrect or not provided when the frontend is hosted separately, leading to failed API calls.fixSet the `url` prop on `FrappeProvider` to the correct address of your Frappe backend: `<FrappeProvider url="https://your-frappe-server.com">`. -
TypeError: Class constructor FrappeProvider cannot be invoked without 'new'
cause Attempting to use CommonJS `require()` syntax to import `FrappeProvider` in an environment that expects ESM imports (typical for modern React projects).fixUse ES module import syntax: `import { FrappeProvider } from 'frappe-react-sdk';` -
Request failed with status code 401 (Unauthorized)
cause API request failed due to missing or invalid authentication credentials. This can happen if not logged in, or if token-based auth is misconfigured.fixEnsure the user is logged in via `useFrappeAuth().login()`, or if using token-based authentication, verify that the `token` prop is correctly passed to `FrappeProvider` and is valid. -
TypeError: Cannot read properties of undefined (reading 'data') when using `useFrappeGetCall`
cause The Frappe API endpoint called by `useFrappeGetCall` returned an error or an unexpected response structure, or the component unmounted before the data arrived.fixImplement robust error handling and loading states. Check the network tab for the exact API response. Ensure optional chaining (`data?.value`) is used when accessing potentially undefined properties.
Warnings
- breaking Version 1.4.0 updated the underlying `frappe-js-sdk` which, in turn, updated Axios to v1. This change might introduce breaking changes in how requests are configured or responses are handled.
- breaking Version 1.13.0 included significant updates to `Axios`, `SWR`, and `frappe-js-sdk`. The changelog explicitly warned this 'might be a breaking change' due to deep dependency updates.
- gotcha The `FrappeProvider` component requires the `url` prop to be explicitly set if your React application is not hosted on the same domain as your Frappe backend. Failure to do so will result in network errors due to incorrect API endpoint resolution.
- gotcha Authentication defaults to cookie-based sessions. If you intend to use token-based authentication (e.g., OAuth bearer tokens or Frappe API Key/Secret pairs), you must explicitly configure it in the `FrappeProvider`.
- gotcha The library extensively uses `SWR` for data fetching and caching. Developers should familiarize themselves with `SWR`'s caching strategies, revalidation options, and potential side effects of overriding `SWR` configurations to avoid unexpected data staleness or excessive re-fetches.
Install
-
npm install frappe-react-sdk -
yarn add frappe-react-sdk -
pnpm add frappe-react-sdk
Imports
- FrappeProvider
const FrappeProvider = require('frappe-react-sdk').FrappeProvider;import { FrappeProvider } from 'frappe-react-sdk'; - useFrappeAuth
import useFrappeAuth from 'frappe-react-sdk/auth';
import { useFrappeAuth } from 'frappe-react-sdk'; - useFrappeDocList
import { useFrappeDocList } from 'frappe-react-sdk/hooks';import { useFrappeDocList } from 'frappe-react-sdk'; - useFrappeGetCall
import { useFrappeGetCall } from 'frappe-react-sdk';
Quickstart
import { FrappeProvider, useFrappeAuth } from 'frappe-react-sdk';
import React from 'react';
function AuthStatus() {
const { currentUser, login, logout, get and maintain user state } = useFrappeAuth();
const handleLogin = async () => {
await login('username', 'password'); // Replace with actual credentials or user input
console.log('Logged in as:', currentUser.fullname);
};
const handleLogout = async () => {
await logout();
console.log('Logged out');
};
return (
<div>
{currentUser ? (
<p>Welcome, {currentUser.fullname || 'User'}! <button onClick={handleLogout}>Logout</button></p>
) : (
<p>Please log in. <button onClick={handleLogin}>Login</button></p>
)}
</div>
);
}
function App() {
// The URL is optional if the web app is hosted on the same URL as the Frappe server.
// Use process.env.FRAPPE_SERVER_URL or a similar environment variable for production.
return (
<FrappeProvider url={process.env.FRAPPE_SERVER_URL ?? 'https://my-frappe-server.frappe.cloud'}>
<h1>Frappe React SDK Demo</h1>
<AuthStatus />
{/* Your other app components would go here */}
</FrappeProvider>
);
}