npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

react-query-external-sync

v2.2.3

Published

A tool for syncing React Query state to an external Dev Tools

Downloads

52,019

Readme

React Query External Sync

A powerful debugging tool for React Query state and device storage in any React-based application. Whether you're building for mobile, web, desktop, TV, or VR - this package has you covered. It works seamlessly across all platforms where React runs, with zero configuration to disable in production.

Pairs perfectly with React Native DevTools for a complete development experience.

React Query External Sync Demo

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

✨ Features

  • 🔄 Real-time React Query state synchronization
  • 💾 Device storage monitoring with CRUD operations - MMKV, AsyncStorage, and SecureStorage
  • 📱 Works with any React-based framework (React, React Native, Expo, Next.js, etc.)
  • 🖥️ Platform-agnostic: Web, iOS, Android, macOS, Windows, Linux, tvOS, VR - you name it!
  • 🔌 Socket.IO integration for reliable communication
  • 📊 Query status, data, and error monitoring
  • ⚡️ Simple integration with minimal setup
  • 🧩 Perfect companion to React Native DevTools
  • 🛑 Zero-config production safety - automatically disabled in production builds

📦 Installation

# Using npm
npm install --save-dev react-query-external-sync socket.io-client

# Using yarn
yarn add -D react-query-external-sync socket.io-client

# Using pnpm
pnpm add -D react-query-external-sync socket.io-client

🚀 Quick Start

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 } from "react-native";
import AsyncStorage from "@react-native-async-storage/async-storage";
import * as SecureStore from "expo-secure-store";
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() {
  // Unified storage queries and external sync - all in one hook!
  useSyncQueriesExternal({
    queryClient,
    socketURL: "http://localhost:42831",
    deviceName: Platform.OS,
    platform: Platform.OS,
    deviceId: Platform.OS,
    extraDeviceInfo: {
      appVersion: "1.0.0",
    },
    enableLogs: true,
    envVariables: {
      NODE_ENV: process.env.NODE_ENV,
    },
    // 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 />;
}

🔒 Production Safety

This 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: [],
  });
}

💡 Usage with DevTools

For the best experience, use this package with the React Native DevTools application:

  1. Download and launch the DevTools application
  2. Integrate this package in your React application
  3. Start your application
  4. DevTools will automatically detect and connect to your running application

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

⚙️ Configuration Options

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 | | extraDeviceInfo | object | No | Additional device metadata to display in DevTools | | enableLogs | boolean | No | Enable console logging for debugging (default: false) | | isDevice | boolean | No | Set to true if this is a device (default: false) | | envVariables | object | No | Environment variables to sync with DevTools | | 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) |

🐛 Troubleshooting

Quick Checklist

  1. DevTools Connection

    • Look for "Connected" status in the top-left corner of the DevTools app
    • If it shows "Disconnected", restart the DevTools app
  2. No Devices Appearing

    • Verify the Socket.IO client is installed (npm list socket.io-client)
    • Ensure the hook is properly set up in your app
    • Check that socketURL matches the DevTools port (default: 42831)
    • Restart both your app and the DevTools
  3. Data Not Syncing

    • Confirm you're passing the correct queryClient instance
    • Set enableLogs: true to see connection information

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

⚠️ 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();
}, []);

📄 License

MIT


Made with ❤️ by LovesWorking