Migrate plugins from Grafana version 11.6.x to 12.0.x
This guide helps you migrate plugins from Grafana version 11.6.x to 12.0.x.
Prerequisites​
Before starting the migration:
- Back up your plugin code
- Ensure your development environment is up to date
- Familiarize yourself with the reactive APIs introduced in Grafana 11.4
Deprecated UI extension APIs removal​
The deprecated UI extension APIs have been removed in Grafana 12 in favor of the new reactive APIs introduced in Grafana 11.4. The following APIs have been removed:
usePluginExtensions()
usePluginLinkExtensions()
usePluginComponentExtensions()
getPluginExtensions()
getPluginLinkExtensions()
getPluginComponentExtensions()
AppPlugin.configureExtensionLink()
AppPlugin.configureExtensionComponent()
Using any of these APIs in Grafana 12 will result in an error. Additionally, the TypeScript types PluginExtensionLinkConfig
and PluginExtensionComponentConfig
have been removed.
If you need your plugin to work with both Grafana 12.0.x and older versions, you can implement runtime checks to conditionally use the appropriate APIs. For more information, refer to Manage backwards compatibility with runtime checks.
AppPlugin.configureExtensionLink()​
Replace the configureExtensionLink
method with the addLink
method. Update the extensionPointId
parameter to targets
, which accepts either a string
or string[]
.
- new AppPlugin().configureExtensionLink({
+ new AppPlugin().addLink({
- extensionPointId: PluginExtensionPoints.DashboardPanelMenu,
+ targets: PluginExtensionPoints.DashboardPanelMenu,
title: 'Component title 0',
description: 'Component description 0',
component: () => <div />,
});
AppPlugin.configureExtensionComponent()​
Replace the configureExtensionComponent
method with the addComponent
method. Update the extensionPointId
parameter to targets
, which accepts either a string
or string[]
.
- new AppPlugin().configureExtensionComponent({
+ new AppPlugin().addComponent({
- extensionPointId: PluginExtensionPoints.CommandPalette,
+ targets: PluginExtensionPoints.CommandPalette,
title: 'Component title 0',
description: 'Component description 0',
component: () => <div />,
});
getPluginLinkExtensions() and usePluginLinkExtensions()​
Both the getPluginLinkExtensions()
function and the usePluginLinkExtensions()
React hook can be replaced with the usePluginLinks()
React hook.
- const { extensions } = getPluginLinkExtensions({
+ const { links, isLoading } = usePluginLinks({
extensionPointId: 'grafana/dashboard/panel/menu/v1',
limitPerPlugin: 2,
context: {
panelId: '...',
},
});
- const { extensions, isLoading } = usePluginLinkExtensions({
+ const { links, isLoading } = usePluginLinks({
extensionPointId: 'grafana/dashboard/panel/menu/v1',
limitPerPlugin: 2,
context: {
panelId: '...',
},
});
getPluginComponentExtensions() and usePluginComponentExtensions()​
You can replace both the getPluginComponentExtensions()
function and the usePluginComponentExtensions()
React hook with the usePluginComponents()
React hook.
- const { extensions } = getPluginComponentExtensions({
+ const { components, isLoading } = usePluginComponents({
extensionPointId: 'grafana/user/profile/tab/v1',
limitPerPlugin: 2,
});
- const { extensions, isLoading } = usePluginComponentExtensions({
+ const { components, isLoading } = usePluginComponents({
extensionPointId: 'grafana/user/profile/tab/v1',
limitPerPlugin: 2,
});
getPluginExtensions() and usePluginExtensions()​
Replace the getPluginExtensions()
function and the usePluginExtensions()
React hook based on their usage:
-
For links: Follow the link extensions instructions.
-
For components: Follow the component extensions instructions.
-
For both links and components: Use both
usePluginLinks
andusePluginComponents
.
PluginExtensionLinkConfig and PluginExtensionComponentConfig​
The types PluginExtensionLinkConfig
and PluginExtensionComponentConfig
have been removed from @grafana/data
. Replace them with PluginExtensionAddedLinkConfig
and PluginExtensionAddedComponentConfig
, respectively.
GetPluginExtensionsOptions​
The GetPluginExtensionsOptions
type has been removed from @grafana/runtime
in favor of specific types that match their corresponding hook parameters.
Quick reference​
The following table summarizes the API changes with notes explaining the key differences:
Deprecated API | Equivalent API | Notes |
---|---|---|
AppPlugin.configureExtensionLink() | AppPlugin.addLink() | extensionPointId parameter renamed to targets , accepts string or string[] |
AppPlugin.configureExtensionComponent() | AppPlugin.addComponent() | extensionPointId parameter renamed to targets , accepts string or string[] |
getPluginLinkExtensions() | usePluginLinks() | Returns { links, isLoading } instead of { extensions } |
usePluginLinkExtensions() | usePluginLinks() | Returns { links, isLoading } instead of { extensions } |
getPluginComponentExtensions() | usePluginComponents() | Returns { components, isLoading } instead of { extensions } |
usePluginComponentExtensions() | usePluginComponents() | Returns { components, isLoading } instead of { extensions, isLoading } |
getPluginExtensions() | usePluginLinks() or usePluginComponents() | Split into two separate hooks based on extension type (links or components) |
usePluginExtensions() | usePluginLinks() or usePluginComponents() | Split into two separate hooks based on extension type (links or components) |
PluginExtensionComponentConfig | PluginExtensionAddedComponentConfig | Updated type definition for component configuration |
PluginExtensionLinkConfig | PluginExtensionAddedLinkConfig | Updated type definition for link configuration |
GetPluginExtensionsOptions | UsePluginLinksOptions or UsePluginComponentsOptions or UsePluginFunctionsOptions | Updated type definition for hook parameters |
Migrate from Select
to Combobox
​
Grafana 11.5.0 introduced the new Combobox
component as a replacement for the Select
component. The Combobox
component has been designed with performance in mind, particularly for handling extremely large data sets. See the component documentation for detailed usage guidelines.
The Select
and MultiSelect
components are now deprecated in Grafana 12 and will not receive substantial updates or fixes. We recommend migrating to Combobox
and MultiCombobox
.
Basic usage​
For simple use cases, the Combobox
component has a similar API to Select
.
/**
* Previous Select implementation
*/
import { SelectableValue } from '@grafana/data';
import { Select } from '@grafana/ui';
const options: SelectableValue[] = [
{ label: 'Loki', value: 'datasource-loki' },
{ label: 'Prometheus', value: 'datasource-prom' },
];
const [value, setValue] = useState<SelectableValue>();
<Select value={value} options={options} onChange={(newOption) => setValue(newOption)} />;
/**
* New Combobox implementation
*/
import { Combobox, ComboboxOption } from '@grafana/ui';
const options: ComboboxOption[] = [
{ label: 'Loki', value: 'datasource-loki' },
{ label: 'Prometheus', value: 'datasource-prom' },
];
// It is preferred to pass in only the 'value' property from options to the value prop
const [value, setValue] = useState<string>();
<Combobox value={value} options={options} onChange={(newOption) => setValue(newOption.value)} />;
Async data loading​
The Combobox
component handles asynchronous data loading through a function passed to the options
prop. This function:
- Receives the current input value as a parameter
- Returns a Promise resolving to
ComboboxOption[]
- Automatically debounces calls to prevent excessive API requests
import { Combobox, ComboboxOption } from '@grafana/ui';
const [value, setValue] = useState<string>();
const loadOptions = useCallback(async (input: string): Promise<ComboboxOption[]> => {
const response = await fetch(`/api/options?query=${input}`);
return response.json();
}, []);
<Combobox value={value} options={loadOptions} onChange={(newOption) => setValue(newOption.value)} />;
Do not request all options on the initial open. It's recommended to use this async behaviour only when calling an API that is able to filter results on the server side.
Quick reference​
The following table summarizes the component deprecations changes with notes explaining the key differences:
Deprecated | Equivalent | Notes |
---|---|---|
Select | Combobox | See props table below |
MultiSelect | MultiCombobox | See props table below |
AsyncSelect | Combobox | Use an async function for the options prop |
VirtualizedSelect | Combobox | Combobox is virtualised by default |
AsyncVirtualizedSelect | Combobox | Combobox is virtualised by default |
AsyncMultiSelect | MultiSelect | Use an async function for the options prop |
The following table summarizes the prop changes with notes explaining the key differences:
Deprecated | Equivalent | Notes |
---|---|---|
SelectableValue | ComboboxOption | Is exported from @grafana/ui instead |
SelectableValue["value"] | ComboboxOption["value"] | Value is required and must be primitive string | number |
SelectableValue["description"] | ComboboxOption["description"] | Description is no longer wrapped and may be truncated |
onChange | onChange | Recommended to only store the value in state |
value | value | Recommended to only pass in the primitive string | number value |
options | options | Can be a ComboboxOption[] or a function that returns a Promise<ComboboxOption[]> |
isLoading | loading | Not required if using async options |
allowCustomValue | createCustomValue | Will emit an object like { label: "Foo", value: "Foo" } from onChange |
width="auto" | width="auto" | minWidth is required when using the auto-sizing input |
Many props from the old Select component that controlled subtle behavior or customized rendering - such as createOptionPosition
or openMenuOnFocus
- are no longer supported, in order to simplify the API and provide a more consistent experience. If you have a specific use case that requires this, please open an issue in the Grafana repo.