Merge pull request #34406 from F-Secure-web/replace-react-use-recommendations-with-react-hookz-web

docs: Replace `react-use` recommendations with `@react-hookz/web`
This commit is contained in:
Fredrik Adelöw
2026-05-27 16:13:10 +02:00
committed by GitHub
3 changed files with 33 additions and 22 deletions
@@ -28,7 +28,7 @@ function useTodos() {
const data = await response.json();
return data.items;
}, [fetch]);
});
}
```
@@ -37,8 +37,8 @@ Here, we're using Backstage's `fetchApi` which wraps the browser `fetch` and aut
1. Injects authentication credentials - you don't need to attach any `Authorization` headers manually.
2. Resolves `plugin://<pluginId>` URL schemes to the real plugin URL for your instance.
The `useAsync` hook from `react-use` runs the async function on mount and
returns `{ value, loading, error }`, which the component uses to show a
The `useAsync` hook from `@react-hookz/web` runs the async function on mount and
returns `[{ status, result, error }, { execute }]`, which the component uses to show a
loading spinner, example todo items if the backend request fails, or the
fetched todo list.
+15 -9
View File
@@ -26,13 +26,15 @@ such as `axios`.
Example:
```ts title="plugins/my-awesome-plugin/src/components/AwesomeUsersTable.tsx"
import useAsync from 'react-use/esm/useAsync';
import { useAsync, useMountEffect } from '@react-hookz/web';
function AwesomeUsersTable() {
const { value, loading, error } = useAsync(async () => {
const [{ status, result, error }, { execute }] = useAsync(async () => {
const response = await fetch('https://api.frobsco.com/v1/list');
return response.json();
}, []);
});
useMountEffect(execute);
...
@@ -94,17 +96,19 @@ import {
discoveryApiRef,
fetchApiRef,
} from '@backstage/core-plugin-api';
import useAsync from 'react-use/esm/useAsync';
import { useAsync, useMountEffect } from '@react-hookz/web';
function FrobsAggregator() {
const fetchApi = useApi(fetchApiRef);
const discoveryApi = useApi(discoveryApiRef);
const { value, loading, error } = useAsync(async () => {
const [{ status, result, error }, { execute }] = useAsync(async () => {
const baseUrl = await discoveryApi.getBaseUrl('proxy');
const response = await fetchApi.fetch(`${baseUrl}/frobs`);
return response.json();
}, [fetchApi, discoveryApi]);
});
useMountEffect(execute);
// ...
}
@@ -171,19 +175,21 @@ import {
discoveryApiRef,
fetchApiRef,
} from '@backstage/core-plugin-api';
import useAsync from 'react-use/esm/useAsync';
import { useAsync, useMountEffect } from '@react-hookz/web';
function FrobsAggregator() {
const fetchApi = useApi(fetchApiRef);
const discoveryApi = useApi(discoveryApiRef);
const { value, loading, error } = useAsync(async () => {
const [{ status, result, error }, { execute }] = useAsync(async () => {
// highlight-next-line
const baseUrl = await discoveryApi.getBaseUrl('frobs-aggregator');
// highlight-next-line
const response = await fetchApi.fetch(`${baseUrl}/summary`);
return response.json();
}, [fetchApi, discoveryApi]);
});
useMountEffect(execute);
// ...
}
@@ -21,11 +21,12 @@ If your plugin requires access to an API, backstage offers
- [Setting up the backstage proxy](#setting-up-the-backstage-proxy)
- [Calling an API using the backstage proxy](#calling-an-api-using-the-backstage-proxy)
- [Option 1: Calling the proxy directly from the frontend plugin](#option-1-calling-the-proxy-directly-from-the-frontend-plugin)
- [Option 2: Defining the API client interface](#defining-the-api-client-interface)
- [Creating the API client](#creating-the-api-client)
- [Bundling your ApiRef with your plugin](#bundling-your-apiref-with-your-plugin)
- [Using the API in your components](#using-the-api-in-your-components)
- [Option 1: Calling the proxy directly from the frontend plugin](#option-1-calling-the-proxy-directly-from-the-frontend-plugin)
- [Option 2: Defining the API client interface](#option-2-defining-the-api-client-interface)
- [Defining the API client interface](#defining-the-api-client-interface)
- [Creating the API client](#creating-the-api-client)
- [Bundling your ApiRef with your plugin](#bundling-your-apiref-with-your-plugin)
- [Using the API in your components](#using-the-api-in-your-components)
## Setting up the backstage proxy
@@ -71,20 +72,22 @@ import {
fetchApiRef,
} from '@backstage/core-plugin-api';
import { Progress, Alert } from '@backstage/core-components';
import useAsync from 'react-use/esm/useAsync';
import { useAsync, useMountEffect } from '@react-hookz/web';
import { myAwesomeApiRef } from '../../api';
export const AwesomeUsersTable = () => {
const fetchApi = useApi(fetchApiRef);
const discoveryApi = useApi(discoveryApiRef);
const { value, loading, error } = useAsync(async () => {
const [{ status, result, error }, { execute }] = useAsync(async () => {
const baseUrl = await discoveryApi.getBaseUrl('proxy');
// As configured previously for the backend proxy
const resp = await fetchApi.fetch(`${baseUrl}/<your-proxy-uri>`);
if (!resp.ok) throw new Error(resp.statusText);
return resp.json();
}, [fetchApi, discoveryApi]);
});
useMountEffect(execute);
// ...
};
@@ -238,16 +241,18 @@ Now you should be able to access your API using the backstage hook
```ts title="plugins/my-awesome-plugin/src/components/AwesomeUsersTable.tsx"
import { useApi } from '@backstage/core-plugin-api';
import { myAwesomeApiRef } from '../../api';
import useAsync from 'react-use/esm/useAsync';
import { useAsync, useMountEffect } from '@react-hookz/web';
export const AwesomeUsersTable = () => {
const apiClient = useApi(myAwesomeApiRef);
const { value, loading, error } = useAsync(async () => {
const [{ status, result, error }, { execute }] = useAsync(async () => {
const users = await apiClient.listUsers();
return users;
}, [apiClient]);
useMountEffect(execute);
// ...
};
```