Abappi
19

Expo DevTools 3.0: What Changed and How to Upgrade from 2.x

3 min readAxonpack Open Source
axonpackReactnativeOpen Sourceexpodevtools

Expo DevTools 3.0 is now available.

This release introduces a simpler setup API and several changes to how DevTools is initialized and integrated into Expo applications.

If you're currently using @axonpack/expo-devtools 2.x, this guide gives you a quick overview of the migration and the main changes you need to know.

What's Changed in 3.0?

The main changes include:

  • A new DevtoolsProvider-based setup
  • Removal of the DevTools client instance
  • Changes to WebView integration
  • Changes to how devtools APIs are imported
  • Behavioral changes around startup and crash capture
  • New APIs for controlling the DevTools panel
  • Removal of webviewSources

Most existing configuration remains compatible. The network, console, performance, storage, and crash configuration fields keep the same structure.

1. A Simpler DevTools Setup

In 2.x, you had to create a DevTools client, initialize it, and mount the overlay separately.

In 3.0, this is replaced with DevtoolsProvider.

Example:

<DevtoolsProvider config={{ enabled: __DEV__ }}>

The condition you previously used to control whether DevTools was mounted can now be passed through the enabled configuration.

It doesn't have to be \_\_DEV\_\_. You can use an environment variable, a configuration value, or another condition depending on your application.

For larger configurations, you can keep the configuration in its own file:

import type { DevtoolsConfig } from '@axonpack/expo-devtools';

export const devtoolsConfig = {

enabled: __DEV__,

// ...your configuration

} satisfies DevtoolsConfig;

2. WebView Integration

WebView integration has also been simplified.

Previously, several properties had to be wired directly from the DevTools client.

In 3.0, you can use useDevtoolsWebView():

const devtoolsWebView = useDevtoolsWebView('checkout');

<WebView

{...devtoolsWebView}

source={{ uri }}

/>

The WebView name is now passed directly to the hook.

Because of this change, webviewSources should be removed from your configuration.

3. Import devtools Directly

APIs such as:

  • mark
  • measure
  • clearMarks
  • clearMeasures
  • setCrashContext
  • DevTools stores

keep their existing names and signatures.

The main difference is where they come from.

Instead of importing your own client instance:

import { devtools } from '../devtools';

Import it directly from the package:

import { devtools } from '@axonpack/expo-devtools';

What Moved?

2.x3.0
createDevtoolsClient(config)<DevtoolsProvider config={config}>
devtools.init()Removed
<DevtoolsOverlay />Integrated into <DevtoolsProvider>
Overlay mount conditionconfig.enabled
config.webviewSourcesRemoved
getWebViewRef()useDevtoolsWebView().ref
getWebViewUserAgent()useDevtoolsWebView().userAgent
handleWebViewMessageuseDevtoolsWebView().onMessage
DevtoolsClientConfigDevtoolsConfig
DevtoolsOverlayPropsDevtoolsProviderProps

Behavioral Changes

There are two important behavioral changes to be aware of.

DevTools Capture Startup

Capture now starts when the provider renders rather than when the module is evaluated.

It still starts before child components mount, so requests from the first screen are captured.

However, requests made while modules are being evaluated may happen before DevTools starts capturing them.

If you previously moved init() ahead of Expo Router's entry file to capture those requests, that workaround is no longer applicable.

Instead, let the root layout hold the provider.

Crash Capture

crash.enableWhileDevtoolsDisabled now installs at the provider's first render.

It still captures crashes when:

enabled: false

The flag continues to capture only crashes that terminate the application.

New in 3.0

useDevtoolsPanel()

You can now control the DevTools panel from your own UI:

const { open, close } = useDevtoolsPanel();

This allows you to build custom controls for opening and closing the panel.

Hide the Floating Button

If you want the panel functionality without displaying the default launcher button:

<DevtoolsProvider

config={{

enabled: __DEV__,

}}

showFloatingButton={false}

\>

The panel remains available even when the floating button is hidden.

Migration Checklist

If you're upgrading from 2.x:

  • Replace createDevtoolsClient() with DevtoolsProvider
  • Remove devtools.init()
  • Remove the separate DevtoolsOverlay
  • Move your enable/disable condition to config.enabled
  • Move WebView wiring to useDevtoolsWebView()
  • Remove webviewSources
  • Import devtools directly from @axonpack/expo-devtools
  • Review code that depended on early init() execution
  • Check your crash configuration
  • Consider using useDevtoolsPanel() for custom controls

Full Upgrade Guide

I've documented the complete migration here:

https://axonpack.github.io/docs/expo-devtools/upgrading

GitHub:

https://github.com/axonpack/expo-devtools

If you're already using Expo DevTools, I'd love to hear your feedback, issues, and suggestions.