|
1 | 1 | # React Query External Sync
|
2 | 2 |
|
3 |
| -A tool for syncing React Query state to an external React Query Dev Tools instance. |
| 3 | +A powerful debugging tool for React Query state 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. |
4 | 4 |
|
5 |
| -## Features |
| 5 | +Pairs perfectly with [React Native DevTools](https://github.com/LovesWorking/rn-better-dev-tools) for a complete development experience. |
6 | 6 |
|
7 |
| -- Works in both React Native and browser/web environments |
8 |
| -- Syncs React Query state between your app and external dev tools |
9 |
| -- Automatically detects platform (iOS, Android, Web, etc.) |
10 |
| -- Handles platform-specific networking (like Android emulator's 10.0.2.2 for localhost) |
11 |
| -- Uses appropriate storage mechanisms based on environment |
| 7 | + |
12 | 8 |
|
13 |
| -## Installation |
| 9 | +## ✨ Features |
14 | 10 |
|
15 |
| -```bash |
16 |
| -npm install react-query-external-sync |
17 |
| -# or |
18 |
| -yarn add react-query-external-sync |
19 |
| -``` |
20 |
| - |
21 |
| -### React Native Requirements |
| 11 | +- 🔄 Real-time React Query state synchronization |
| 12 | +- 📱 Works with any React-based framework (React, React Native, Expo, Next.js, etc.) |
| 13 | +- 🖥️ Platform-agnostic: Web, iOS, Android, macOS, Windows, Linux, tvOS, VR - you name it! |
| 14 | +- 🔌 Socket.IO integration for reliable communication |
| 15 | +- 📊 Query status, data, and error monitoring |
| 16 | +- ⚡️ Simple integration with minimal setup |
| 17 | +- 🧩 Perfect companion to React Native DevTools |
| 18 | +- 🛑 Zero-config production safety - automatically disabled in production builds |
22 | 19 |
|
23 |
| -If you're using this in a React Native project, you'll need to install the following optional dependencies: |
| 20 | +## 📦 Installation |
24 | 21 |
|
25 | 22 | ```bash
|
26 |
| -npm install react-native @react-native-async-storage/async-storage |
27 |
| -# or |
28 |
| -yarn add react-native @react-native-async-storage/async-storage |
| 23 | +# Using npm |
| 24 | +npm install --save-dev react-query-external-sync socket.io-client |
| 25 | + |
| 26 | +# Using yarn |
| 27 | +yarn add -D react-query-external-sync socket.io-client |
| 28 | + |
| 29 | +# Using pnpm |
| 30 | +pnpm add -D react-query-external-sync socket.io-client |
29 | 31 | ```
|
30 | 32 |
|
31 |
| -## Usage |
| 33 | +## 🚀 Quick Start |
| 34 | + |
| 35 | +Add the hook to your application where you set up your React Query context: |
32 | 36 |
|
33 | 37 | ```jsx
|
34 |
| -import { useQuerySyncSocket } from 'react-query-external-sync'; |
| 38 | +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; |
| 39 | +import { useSyncQueriesExternal } from "react-query-external-sync"; |
| 40 | +// Import Platform for React Native or use other platform detection for web/desktop |
| 41 | +import { Platform } from "react-native"; |
35 | 42 |
|
36 |
| -function App() { |
37 |
| - // Set up the sync socket |
38 |
| - useQuerySyncSocket({ |
39 |
| - deviceName: 'MyApp', // Name to identify this device |
40 |
| - socketURL: 'http://localhost:42831', // URL to your dev tools instance |
41 |
| - }); |
| 43 | +// Create your query client |
| 44 | +const queryClient = new QueryClient(); |
42 | 45 |
|
| 46 | +function App() { |
43 | 47 | return (
|
44 |
| - // Your app components |
| 48 | + <QueryClientProvider client={queryClient}> |
| 49 | + <AppContent /> |
| 50 | + </QueryClientProvider> |
45 | 51 | );
|
46 | 52 | }
|
| 53 | + |
| 54 | +function AppContent() { |
| 55 | + // Set up the sync hook - automatically disabled in production! |
| 56 | + useSyncQueriesExternal({ |
| 57 | + queryClient, |
| 58 | + socketURL: "http://localhost:42831", // Default port for React Native DevTools |
| 59 | + deviceName: Platform?.OS || "web", // Platform detection |
| 60 | + platform: Platform?.OS || "web", // Use appropriate platform identifier |
| 61 | + deviceId: Platform?.OS || "web", // Use a PERSISTENT identifier (see note below) |
| 62 | + extraDeviceInfo: { |
| 63 | + // Optional additional info about your device |
| 64 | + appVersion: "1.0.0", |
| 65 | + // Add any relevant platform info |
| 66 | + }, |
| 67 | + enableLogs: false, |
| 68 | + }); |
| 69 | + |
| 70 | + // Your app content |
| 71 | + return <YourApp />; |
| 72 | +} |
| 73 | +``` |
| 74 | + |
| 75 | +## 🔒 Production Safety |
| 76 | + |
| 77 | +This package is automatically disabled in production builds. |
| 78 | + |
| 79 | +```jsx |
| 80 | +// The package handles this internally: |
| 81 | +if (process.env.NODE_ENV !== "production") { |
| 82 | + useSyncQueries = require("./new-sync/useSyncQueries").useSyncQueries; |
| 83 | +} else { |
| 84 | + // In production, this becomes a no-op function |
| 85 | + useSyncQueries = () => ({ |
| 86 | + isConnected: false, |
| 87 | + connect: () => {}, |
| 88 | + disconnect: () => {}, |
| 89 | + socket: null, |
| 90 | + users: [], |
| 91 | + }); |
| 92 | +} |
47 | 93 | ```
|
48 | 94 |
|
49 |
| -## How It Works |
| 95 | +## 💡 Usage with DevTools |
50 | 96 |
|
51 |
| -This package provides a cross-platform solution for syncing React Query state to external tools: |
| 97 | +For the best experience, use this package with the [React Native DevTools](https://github.com/LovesWorking/rn-better-dev-tools) application: |
52 | 98 |
|
53 |
| -1. **Platform Detection**: Automatically detects if running in React Native or web environment |
54 |
| -2. **Storage Abstraction**: Uses the appropriate storage mechanism: |
55 |
| - - React Native: AsyncStorage (if available) |
56 |
| - - Web: localStorage |
57 |
| - - Fallback: In-memory storage |
58 |
| -3. **Network Configuration**: Handles platform-specific networking requirements |
59 |
| - - For Android emulators: Maps localhost to 10.0.2.2 |
60 |
| - - For other environments: Uses the provided URL |
| 99 | +1. Download and launch the DevTools application |
| 100 | +2. Integrate this package in your React application |
| 101 | +3. Start your application |
| 102 | +4. DevTools will automatically detect and connect to your running application |
61 | 103 |
|
62 |
| -## Advanced Configuration |
| 104 | +> **Note**: For optimal connection, launch DevTools before starting your application. |
63 | 105 |
|
64 |
| -### Custom Platform Detection |
| 106 | +## ⚙️ Configuration Options |
65 | 107 |
|
66 |
| -If you need to override the built-in platform detection: |
| 108 | +The `useSyncQueriesExternal` hook accepts the following options: |
67 | 109 |
|
68 |
| -```jsx |
69 |
| -import { |
70 |
| - useQuerySyncSocket, |
71 |
| - setPlatformOverride, |
72 |
| -} from "react-query-external-sync"; |
| 110 | +| Option | Type | Required | Description | |
| 111 | +| ----------------- | ----------- | -------- | ----------------------------------------------------------------------- | |
| 112 | +| `queryClient` | QueryClient | Yes | Your React Query client instance | |
| 113 | +| `socketURL` | string | Yes | URL of the socket server (e.g., 'http://localhost:42831') | |
| 114 | +| `deviceName` | string | Yes | Human-readable name for your device | |
| 115 | +| `platform` | string | Yes | Platform identifier ('ios', 'android', 'web', 'macos', 'windows', etc.) | |
| 116 | +| `deviceId` | string | Yes | Unique identifier for your device | |
| 117 | +| `extraDeviceInfo` | object | No | Additional device metadata to display in DevTools | |
| 118 | +| `enableLogs` | boolean | No | Enable console logging for debugging (default: false) | |
73 | 119 |
|
74 |
| -// Set a custom platform |
75 |
| -setPlatformOverride({ os: "customOS", name: "Custom Platform" }); |
| 120 | +## 🐛 Troubleshooting |
76 | 121 |
|
77 |
| -// Use normally after setting override |
78 |
| -function App() { |
79 |
| - useQuerySyncSocket({ |
80 |
| - deviceName: "MyCustomPlatformApp", |
81 |
| - socketURL: "http://localhost:3000", |
82 |
| - }); |
| 122 | +### Quick Checklist |
83 | 123 |
|
84 |
| - // ... |
85 |
| -} |
86 |
| -``` |
| 124 | +1. **DevTools Connection** |
| 125 | + |
| 126 | + - Look for "Connected" status in the top-left corner of the DevTools app |
| 127 | + - If it shows "Disconnected", restart the DevTools app |
87 | 128 |
|
88 |
| -### Custom Storage |
| 129 | +2. **No Devices Appearing** |
89 | 130 |
|
90 |
| -If you need to provide a custom storage implementation: |
| 131 | + - Verify the Socket.IO client is installed (`npm list socket.io-client`) |
| 132 | + - Ensure the hook is properly set up in your app |
| 133 | + - Check that `socketURL` matches the DevTools port (default: 42831) |
| 134 | + - Restart both your app and the DevTools |
| 135 | + |
| 136 | +3. **Data Not Syncing** |
| 137 | + - Confirm you're passing the correct `queryClient` instance |
| 138 | + - Set `enableLogs: true` to see connection information |
| 139 | + |
| 140 | +That's it! If you're still having issues, visit the [GitHub repository](https://github.com/LovesWorking/react-query-external-sync/issues) for support. |
| 141 | + |
| 142 | +## ⚠️ Important Note About Device IDs |
| 143 | + |
| 144 | +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. |
| 145 | + |
| 146 | +**Recommended approaches:** |
91 | 147 |
|
92 | 148 | ```jsx
|
93 |
| -import { |
94 |
| - useQuerySyncSocket, |
95 |
| - setCustomStorage, |
96 |
| -} from "react-query-external-sync"; |
97 |
| - |
98 |
| -// Set a custom storage implementation |
99 |
| -setCustomStorage({ |
100 |
| - getItem: async (key) => { |
101 |
| - /* your implementation */ |
102 |
| - }, |
103 |
| - setItem: async (key, value) => { |
104 |
| - /* your implementation */ |
105 |
| - }, |
106 |
| - removeItem: async (key) => { |
107 |
| - /* your implementation */ |
108 |
| - }, |
109 |
| -}); |
110 |
| - |
111 |
| -// Use normally after setting custom storage |
112 |
| -function App() { |
113 |
| - // ... |
114 |
| -} |
| 149 | +// Simple approach for single devices |
| 150 | +deviceId: Platform.OS, // Works if you only have one device per platform |
| 151 | + |
| 152 | +// Better approach for multiple simulators/devices of same type |
| 153 | +// Using AsyncStorage, MMKV, or another storage solution |
| 154 | +const [deviceId, setDeviceId] = useState(Platform.OS); |
| 155 | + |
| 156 | +useEffect(() => { |
| 157 | + const loadOrCreateDeviceId = async () => { |
| 158 | + // Try to load existing ID |
| 159 | + const storedId = await AsyncStorage.getItem('deviceId'); |
| 160 | + |
| 161 | + if (storedId) { |
| 162 | + setDeviceId(storedId); |
| 163 | + } else { |
| 164 | + // First launch - generate and store a persistent ID |
| 165 | + const newId = `${Platform.OS}-${Date.now()}`; |
| 166 | + await AsyncStorage.setItem('deviceId', newId); |
| 167 | + setDeviceId(newId); |
| 168 | + } |
| 169 | + }; |
| 170 | + |
| 171 | + loadOrCreateDeviceId(); |
| 172 | +}, []); |
115 | 173 | ```
|
116 | 174 |
|
117 |
| -## License |
| 175 | +## 📄 License |
118 | 176 |
|
119 | 177 | MIT
|
120 | 178 |
|
121 |
| -<br> |
122 |
| -<hr> |
123 |
| -<br> |
| 179 | +--- |
| 180 | + |
| 181 | +Made with ❤️ by [LovesWorking](https://github.com/LovesWorking) |
0 commit comments