# Migrate plugins from Grafana version 9.x to 10.x

Follow these instructions to migrate plugins from Grafana version 9.x to 10.x.

## Verify plugin behavior with React 18[​](#verify-plugin-behavior-with-react-18 "Direct link to Verify plugin behavior with React 18")

Grafana 10 includes our upgrade to React 18 and use of the new React client-side rendering API. These changes were delivered to the core `grafana` repo with [PR 64428](https://github.com/grafana/grafana/pull/64428).

Although these updates bring many significant benefits, there's a potential for them to impact the way that your plugin works. In particular, there could be unintended side effects caused by the changes around improving consistency with `useEffect` timings and automatic batching of state updates.

**Recommended actions:**

* Review the React 18 [upgrade docs](https://react.dev/blog/2022/03/08/react-18-upgrade-guide).
* Test your plugins against one of the latest [grafana-dev docker images](https://hub.docker.com/r/grafana/grafana-dev/tags?page=1) (for example, [this one](https://hub.docker.com/layers/grafana/grafana-dev/10.0.0-111404pre/images/sha256-ac78acf54b44bd2ce7e68b796b1df47030da7f35e53b02bc3eec3f4de05f780f?context=explore)).
* If your plugin is affected, add a comment to the [forum discussion](https://community.grafana.com/t/grafana-10-is-upgrading-to-react-18/86051). Be sure to communicate with us so we are aware of the issue and can provide help.

## Data frame field values are now just arrays[​](#data-frame-field-values-are-now-just-arrays "Direct link to Data frame field values are now just arrays")

In Grafana 10, the values in data frames are now managed as simple JavaScript arrays (see [PR #66480](https://github.com/grafana/grafana/issues/66480)). It is no longer necessary to wrap values in a [`Vector<T>`](https://github.com/grafana/grafana/blob/v9.5.x/packages/grafana-data/src/types/vector.ts) implementation.c

Most code targeting 9.x will continue to work without any issues. An exception is the rare case in which existing code directly implements [`Vector<T>`](https://github.com/grafana/grafana/blob/v9.5.x/packages/grafana-data/src/types/vector.ts) rather than extending or using base classes. In this case, the code should either return an array or extend [`FunctionalVector<T>`](https://github.com/grafana/grafana/blob/v10.0.x/packages/grafana-data/src/vector/FunctionalVector.ts#L9). All Vector implementations have been deprecated and will be removed in the future.

When writing plugins that should run on 9.x, continue to use the Vector interfaces. In this case, when targeting versions 10+, you can now use simple arrays rather than wrapper classes.

To make this transition seamless, we employed the Original JavaScript Sin™. That is, we [extended the native Array prototype](https://github.com/grafana/grafana/blob/v10.0.x/packages/grafana-data/src/types/vector.ts) with several Vector methods.

## Update to React Router v6[​](#update-to-react-router-v6 "Direct link to Update to React Router v6")

Starting from Grafana 10, plugins can start using the v6 of `react-router`. Overall, `react-router` v6 aims to simplify route configuration and provide a more flexible and intuitive API for developers.

If your current plugin version needs to maintain compatibility with Grafana v9, then you can continue to use `react-router@v5` in Grafana v10. Both versions are available for plugins. However, **we strongly encourage developers to update their plugins to use the v6 version `react-router` as soon as possible**, as the v5 version is going to be deprecated in Grafana v11 and subsequently removed.

For more general information, refer to the [Official React Router v5 to v6 migration guide](https://reactrouter.com/en/main/upgrading/v5).

### Update using `@grafana/create-plugin`[​](#update-using-grafanacreate-plugin "Direct link to update-using-grafanacreate-plugin")

Follow the steps below to start using `react-router` v6 in your plugin:

#### 1. Update the build related configuration:[​](#1-update-the-build-related-configuration "Direct link to 1. Update the build related configuration:")

Enable using `react-router@v6` by setting the following feature flag in `<project-root>/.cprc.json`:

\<project-root>/.cprc.json

```json
{
  "features": {
    "useReactRouterV6": true
  }
}

```

Now update the build configuration using the create-plugin tool:

* npm
* Yarn
* pnpm

```shell
npx @grafana/create-plugin@latest update

```

```shell
yarn dlx @grafana/create-plugin@latest update

```

```shell
pnpm dlx @grafana/create-plugin@latest update

```

After updating the build configuration, it is likely that you will need to make additional updates to your plugin. To do so, follow the steps below:

#### 2. Use `<Routes>` instead of `<Switch>`[​](#2-use-routes-instead-of-switch "Direct link to 2-use-routes-instead-of-switch")

src/Routes.tsx

```typescript
// Using <Routes> instead of <Switch> in `react-router` v6
import { Routes } from 'react-router-dom';

// ...

return (
  <Routes>
    <Route path="/" element={<Home />} />
  </Routes>
);

```

#### 3. Remove the `exact` prop from `<Route>` components[​](#3-remove-the-exact-prop-from-route-components "Direct link to 3-remove-the-exact-prop-from-route-components")

src/Routes.tsx

```typescript
return (
  <Routes>
    {/* BAD (Until v5) */}
    <Route exact path="/" element={<Home />} />

    {/* GOOD (From v6) */}
    {/* (Routes are "exact" by default, you need to use the "*" to match sub-routes) */}
    <Route path="/" element={<Home />} />
  </Routes>
);

```

#### 4. Fix test failures with location service methods[​](#4-fix-test-failures-with-location-service-methods "Direct link to 4. Fix test failures with location service methods")

When using `locationService.replace()`, `locationService.push()`, or similar methods from `@grafana/runtime`, your tests might fail after migrating to React Router v6. Solve this by using the `<LocationServiceProvider />` component (introduced in Grafana 11.2.0) to create a provider for the location service in your tests.

test/test-utils.tsx

```typescript
import { locationService, LocationServiceProvider } from '@grafana/runtime';
import React, { useEffect, useState } from 'react';
import { Router } from 'react-router-dom';

const history = locationService.getHistory();

export function TestRoutesProvider({ children }: { children: React.ReactNode }) {
  const [location, setLocation] = useState(history.location);

  useEffect(() => {
    history.listen(setLocation);
  }, []);

  return (
    <LocationServiceProvider service={locationService}>
      <Router navigator={history} location={location}>
        {children}
      </Router>
    </LocationServiceProvider>
  );
}

```

#### 5. Follow the original `react-router` migration guide for more in-depth changes[​](#5-follow-the-original-react-router-migration-guide-for-more-in-depth-changes "Direct link to 5-follow-the-original-react-router-migration-guide-for-more-in-depth-changes")

Visit the [official react-router v5 to v6 migration guide](https://reactrouter.com/en/main/upgrading/v5) for more information.
