A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://github.com/LovesWorking/rn-better-dev-tools below:

LovesWorking/rn-better-dev-tools: Beautiful macOS app for debugging React Query in ANY React-based application (Mobile, Web, TV, VR). Monitor queries across devices in real-time with a gorgeous native interface. Features device management, query visualization, state simulation, and automatic production safety. Works with React Native, Web, Next.js, Expo, and any JS based platform

Enhanced developer tools for React Native applications, supporting React Query DevTools and device storage monitoring with a beautiful native interface.

431415919-fce3cba3-b30a-409a-8f8f-db2bd28579be.mp4

https://github.com/LovesWorking/RN-Dev-Tools-Example

If you need internal React Query dev tools within the device you can use my other package here!

https://github.com/LovesWorking/react-native-react-query-devtools

DevTools Desktop Application (macOS)

⚠️ Important: The desktop app has currently only been tested on Apple Silicon Macs (M1/M2/M3). If you encounter issues on Intel-based Macs, please open an issue and we'll work together to fix it.

  1. Download the latest release from the Releases page
  2. Extract the ZIP file
  3. Move the app to your Applications folder
  4. Launch the app
React Application Integration

The easiest way to connect your React application to the DevTools is by installing the npm package:

# Using npm
npm install --save-dev react-query-external-sync socket.io-client
npm install expo-device  # For automatic device detection

# Using yarn
yarn add -D react-query-external-sync socket.io-client
yarn add expo-device  # For automatic device detection

# Using pnpm (recommended)
pnpm add -D react-query-external-sync socket.io-client
pnpm add expo-device  # For automatic device detection
  1. Download and launch the React Native DevTools application
  2. Add the hook to your application where you set up your React Query context:
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { useSyncQueriesExternal } from "react-query-external-sync";
// Import Platform for React Native or use other platform detection for web/desktop
import { Platform } from "react-native";
import AsyncStorage from "@react-native-async-storage/async-storage";
import * as SecureStore from "expo-secure-store";
import * as ExpoDevice from "expo-device";
import { storage } from "./mmkv"; // Your MMKV instance

// Create your query client
const queryClient = new QueryClient();

function App() {
  return (
    <QueryClientProvider client={queryClient}>
      <AppContent />
    </QueryClientProvider>
  );
}

function AppContent() {
  // Set up the sync hook - automatically disabled in production!
  useSyncQueriesExternal({
    queryClient,
    socketURL: "http://localhost:42831", // Default port for React Native DevTools
    deviceName: Platform?.OS || "web", // Platform detection
    platform: Platform?.OS || "web", // Use appropriate platform identifier
    deviceId: Platform?.OS || "web", // Use a PERSISTENT identifier (see note below)
    isDevice: ExpoDevice.isDevice, // Automatically detects real devices vs emulators
    extraDeviceInfo: {
      // Optional additional info about your device
      appVersion: "1.0.0",
      // Add any relevant platform info
    },
    enableLogs: false,
    envVariables: {
      NODE_ENV: process.env.NODE_ENV,
      // Add any private environment variables you want to monitor
      // Public environment variables are automatically loaded
    },
    // Storage monitoring with CRUD operations
    mmkvStorage: storage, // MMKV storage for ['#storage', 'mmkv', 'key'] queries + monitoring
    asyncStorage: AsyncStorage, // AsyncStorage for ['#storage', 'async', 'key'] queries + monitoring
    secureStorage: SecureStore, // SecureStore for ['#storage', 'secure', 'key'] queries + monitoring
    secureStorageKeys: [
      "userToken",
      "refreshToken",
      "biometricKey",
      "deviceId",
    ], // SecureStore keys to monitor
  });

  // Your app content
  return <YourApp />;
}
  1. Start your React application
  2. DevTools will automatically detect and connect to your running application

The React Query External Sync package is automatically disabled in production builds.

// The package handles this internally:
if (process.env.NODE_ENV !== "production") {
  useSyncQueries = require("./new-sync/useSyncQueries").useSyncQueries;
} else {
  // In production, this becomes a no-op function
  useSyncQueries = () => ({
    isConnected: false,
    connect: () => {},
    disconnect: () => {},
    socket: null,
    users: [],
  });
}
📱 Using with Real Devices (Local Network)

When testing on real devices connected to your local network, you'll need to use your host machine's IP address instead of localhost. Here's a helpful setup for Expo apps (contributed by ShoeBoom):

import Constants from "expo-constants";
import AsyncStorage from "@react-native-async-storage/async-storage";
import * as SecureStore from "expo-secure-store";
import { storage } from "./mmkv"; // Your MMKV instance

// Get the host IP address dynamically
const hostIP =
  Constants.expoGoConfig?.debuggerHost?.split(`:`)[0] ||
  Constants.expoConfig?.hostUri?.split(`:`)[0];

function AppContent() {
  useSyncQueriesExternal({
    queryClient,
    socketURL: `http://${hostIP}:42831`, // Use local network IP
    deviceName: Platform?.OS || "web",
    platform: Platform?.OS || "web",
    deviceId: Platform?.OS || "web",
    extraDeviceInfo: {
      appVersion: "1.0.0",
    },
    enableLogs: false,
    envVariables: {
      NODE_ENV: process.env.NODE_ENV,
    },
    // Storage monitoring
    mmkvStorage: storage,
    asyncStorage: AsyncStorage,
    secureStorage: SecureStore,
    secureStorageKeys: ["userToken", "refreshToken"],
  });

  return <YourApp />;
}

Note: For optimal connection, launch DevTools before starting your application.

React Native DevTools works with any React-based application, regardless of platform:

If your platform can run React and connect to a socket server, it will work with these DevTools!

React Native DevTools now includes powerful storage monitoring capabilities with full CRUD operations:

// In your app, use React Query to interact with storage
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";

// Read from MMKV storage
const { data: userData } = useQuery({
  queryKey: ["#storage", "mmkv", "user"],
  // Data will be automatically synced with DevTools
});

// Write to AsyncStorage
const queryClient = useQueryClient();
const updateAsyncStorage = useMutation({
  mutationFn: async ({ key, value }) => {
    await AsyncStorage.setItem(key, JSON.stringify(value));
    // Invalidate to trigger sync
    queryClient.invalidateQueries(["#storage", "async", key]);
  },
});

The useSyncQueriesExternal hook accepts the following options:

Option Type Required Description queryClient QueryClient Yes Your React Query client instance socketURL string Yes URL of the socket server (e.g., 'http://localhost:42831') deviceName string Yes Human-readable name for your device platform string Yes Platform identifier ('ios', 'android', 'web', 'macos', 'windows', etc.) deviceId string Yes Unique identifier for your device isDevice boolean No Whether running on a real device (true) or emulator (false). Used for Android socket URL handling (default: true) extraDeviceInfo object No Additional device metadata to display in DevTools enableLogs boolean No Enable console logging for debugging (default: false) envVariables object No Private environment variables to sync with DevTools (public vars are auto-loaded) mmkvStorage MmkvStorage No MMKV storage instance for real-time monitoring asyncStorage AsyncStorage No AsyncStorage instance for polling-based monitoring secureStorage SecureStore No SecureStore instance for secure data monitoring secureStorageKeys string[] No Array of SecureStore keys to monitor (required if using secureStorage)

React Native DevTools is actively being developed with exciting features on the roadmap:

Stay tuned for updates!

I welcome contributions! See Development Guide for details on:

Having issues? Check these common solutions:

  1. App Not Connecting

  2. App Not Starting

  3. Socket Connection Issues

  4. Data Not Syncing

  5. Android Real Device Connection Issues

  6. DevTools App Issues

  7. Storage Monitoring Issues

That's it! If you're still having issues, visit the GitHub repository for support.

🏷️ Device Type Detection

The isDevice prop helps the DevTools distinguish between real devices and simulators/emulators. This is crucial for Android connectivity - the package automatically handles URL transformation for Android emulators (localhost → 10.0.2.2) but needs to know if you're running on a real device to avoid this transformation.

⚠️ Android Connection Issue

On real Android devices using React Native CLI and ADB, the automatic emulator detection can incorrectly transform localhost to 10.0.2.2, breaking WebSocket connections. Setting isDevice: true prevents this transformation.

Recommended approaches:

// Best approach using Expo Device (works with bare React Native too)
import * as ExpoDevice from "expo-device";

useSyncQueriesExternal({
  queryClient,
  socketURL: "http://localhost:42831",
  deviceName: Platform.OS,
  platform: Platform.OS,
  deviceId: Platform.OS,
  isDevice: ExpoDevice.isDevice, // Automatically detects real devices vs emulators
  // ... other props
});

// Alternative: Simple approach using React Native's __DEV__ flag
isDevice: !__DEV__, // true for production/real devices, false for development/simulators

// Alternative: More sophisticated detection using react-native-device-info
import DeviceInfo from 'react-native-device-info';
isDevice: !DeviceInfo.isEmulator(), // Automatically detects if running on emulator

// Manual control for specific scenarios
isDevice: Platform.OS === 'ios' ? !Platform.isPad : Platform.OS !== 'web',
⚠️ Important Note About Device IDs

The deviceId parameter must be persistent across app restarts and re-renders. Using a value that changes (like Date.now()) will cause each render to be treated as a new device.

Recommended approaches:

// Simple approach for single devices
deviceId: Platform.OS, // Works if you only have one device per platform

// Better approach for multiple simulators/devices of same type
// Using AsyncStorage, MMKV, or another storage solution
const [deviceId, setDeviceId] = useState(Platform.OS);

useEffect(() => {
  const loadOrCreateDeviceId = async () => {
    // Try to load existing ID
    const storedId = await AsyncStorage.getItem('deviceId');

    if (storedId) {
      setDeviceId(storedId);
    } else {
      // First launch - generate and store a persistent ID
      const newId = `${Platform.OS}-${Date.now()}`;
      await AsyncStorage.setItem('deviceId', newId);
      setDeviceId(newId);
    }
  };

  loadOrCreateDeviceId();
}, []);

For more detailed troubleshooting, see our Development Guide.

Made with ❤️ by LovesWorking

Take a shortcut from web developer to mobile development fluency with guided learning

Enjoyed this project? Learn to use React Native to build production-ready, native mobile apps for both iOS and Android based on your existing web development skills.


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4