|
1 | 1 | # React Query External Sync
|
2 | 2 |
|
3 |
| -React Query devtool synced with Socket.IO, to debug your react-query outstide your app easily. |
| 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 |
| - |
| 5 | +Pairs perfectly with [React Native DevTools](https://github.com/LovesWorking/rn-better-dev-tools) for a complete development experience. |
6 | 6 |
|
7 |
| -## Table of content |
| 7 | + |
8 | 8 |
|
9 |
| -- [Introduction](#introduction) |
10 |
| - - [Key Advantages](#key-advantages) |
11 |
| -- [Prerequisites](#prerequisites) |
12 |
| - - [Client Application](#client-application) |
13 |
| - - [Socket IO Server](#socket-io-server) |
14 |
| - - [Devtool Website](#devtool-website) |
15 |
| -- [Installation](#installation) |
16 |
| - + [Client](#client) |
17 |
| - - [1. Install the package](#1-install-the-package) |
18 |
| - - [2. Connect your react-query to the socket](#2-connect-your-react-query-to-the-socket) |
19 |
| - - [3. Usages](#3-usages) |
20 |
| - + [Socket IO Server](#socket-io-server) |
21 |
| - - [1. Install the package](#1-install-the-package-1) |
22 |
| - - [2. Setup Socket IO](#2-setup-socket-io) |
23 |
| - + [React Query Dev Tools Server](#react-query-dev-tools-server) |
24 |
| -- [Ready to use Docker image](#ready-to-use-docker-image) |
25 |
| - - [1. Image link](#1-image-link) |
26 |
| - - [2. Environment variables](#2-environment-variables) |
27 |
| - - [3. Docker Compose example](#3-docker-compose-example) |
28 |
| -- [Contribution](#contribution) |
| 9 | +## ✨ Features |
29 | 10 |
|
30 |
| -## Introduction |
| 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 |
31 | 19 |
|
32 |
| -**React Query External Sync** is a dynamic tool for managing React Query state outside the usual confines of React Query Dev Tools. Ideal for React projects, it offers a live state management solution that's accessible to both developers, qa and non-technical team members. |
33 |
| - |
34 |
| -### Key Advantages: |
35 |
| -- **Real-time UI Updates**: Instantly see how state changes affect your application's UI without backend alterations. |
36 |
| -- **Broad Accessibility**: Enables all team members, including QA, designers, and business professionals, to tweak and test API-driven UI components on the fly. |
37 |
| -- **Continuous Evolution**: Built with expansion in mind, expect regular feature updates driven by community feedback and the evolving needs of modern development workflows. |
38 |
| -- **Enhanced Manipulation**: Future updates will introduce capabilities for precise state adjustments, such as directly inserting complete objects or arrays, object duplication, simultaneous state syncing across web, Android, and iOS and persistent state overrides, allowing values for specific data to remain until manually reverted. |
39 |
| - |
40 |
| -## Prerequisites |
41 |
| - |
42 |
| -### Client Application |
43 |
| - |
44 |
| -- React version 18 or above. |
45 |
| -- React Query version 5.17.19 or above. |
46 |
| - |
47 |
| -### Socket IO Server |
48 |
| - |
49 |
| -- Socket.io version 4.7.4 or above. |
50 |
| - |
51 |
| -### Devtool Website |
52 |
| - |
53 |
| -- Any react.js ready server (vite, rca, ...) |
54 |
| - |
55 |
| -## Installation |
56 |
| - |
57 |
| -### Client |
58 |
| - |
59 |
| -#### 1. Install the package |
| 20 | +## 📦 Installation |
60 | 21 |
|
61 | 22 | ```bash
|
62 |
| -npm install react-query-external-sync |
63 |
| -``` |
| 23 | +# Using npm |
| 24 | +npm install --save-dev react-query-external-sync socket.io-client |
64 | 25 |
|
65 |
| -#### 2. Connect your react-query to the socket |
| 26 | +# Using yarn |
| 27 | +yarn add -D react-query-external-sync socket.io-client |
66 | 28 |
|
67 |
| -- Import the useAllQueries hook and utilize it within your client application to enable real-time synchronization with the external dashboard. |
| 29 | +# Using pnpm |
| 30 | +pnpm add -D react-query-external-sync socket.io-client |
| 31 | +``` |
68 | 32 |
|
69 |
| -```javascript |
70 |
| -import { useAllQueries } from "react-query-external-sync"; |
| 33 | +## 🚀 Quick Start |
| 34 | + |
| 35 | +Add the hook to your application where you set up your React Query context: |
| 36 | + |
| 37 | +```jsx |
| 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"; |
| 42 | + |
| 43 | +// Create your query client |
| 44 | +const queryClient = new QueryClient(); |
| 45 | + |
| 46 | +function App() { |
| 47 | + return ( |
| 48 | + <QueryClientProvider client={queryClient}> |
| 49 | + <AppContent /> |
| 50 | + </QueryClientProvider> |
| 51 | + ); |
| 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 | +``` |
71 | 74 |
|
72 |
| -const { connect, disconnect, isConnected, queries, socket, users } = |
73 |
| - useAllQueries({ |
74 |
| - query: { |
75 |
| - username: "myUsername", |
76 |
| - userType: "User", // Role of the user |
77 |
| - clientType: "client", // client | server |
78 |
| - }, |
79 |
| - queryClient, |
80 |
| - socketURL: "http://localhost:4000", |
81 |
| - }); |
| 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 | +} |
82 | 93 | ```
|
83 | 94 |
|
84 |
| -- **query**: Contains user information for identifying and managing connections in the dashboard. |
85 |
| -- **queryClient**: Your application's React Query client instance. |
86 |
| -- **socketURL**: The URL where your Socket.io server is hosted. |
| 95 | +## 💡 Usage with DevTools |
87 | 96 |
|
88 |
| -#### 3. Usages |
| 97 | +For the best experience, use this package with the [React Native DevTools](https://github.com/LovesWorking/rn-better-dev-tools) application: |
89 | 98 |
|
90 |
| -- `.connect()`: initiate a connection with the socket server |
91 |
| -- `.disconnect()`: terminate the connection to the socket server by invoking the disconnect function |
92 |
| -- `.isConnected`: monitor the connection status |
| 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 |
93 | 103 |
|
94 |
| -### Socket IO Server |
| 104 | +> **Note**: For optimal connection, launch DevTools before starting your application. |
95 | 105 |
|
96 |
| -#### 1. Install the package |
| 106 | +## ⚙️ Configuration Options |
97 | 107 |
|
98 |
| -```bash |
99 |
| -npm install react-query-external-dash |
100 |
| -``` |
| 108 | +The `useSyncQueriesExternal` hook accepts the following options: |
101 | 109 |
|
102 |
| -#### 2. Setup Socket IO |
| 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) | |
103 | 119 |
|
104 |
| -- After setting up your Socket.io server, integrate the socketHandle function to manage incoming and outgoing messages related to query state synchronization. |
105 |
| -- **Basic socket io Nodejs server example**: |
| 120 | +## 🐛 Troubleshooting |
106 | 121 |
|
107 |
| -```javascript |
108 |
| -import { socketHandle } from "react-query-external-dash" |
| 122 | +### Quick Checklist |
109 | 123 |
|
110 |
| -import("socket.io").then(4000 => { |
111 |
| - const io = new socketIO.Server(socketPort, { |
112 |
| - cors: { |
113 |
| - // This origin is the devtool (see next section), change the port to fit your needs. |
114 |
| - // You'll also need to add the URL of your client if you have any CORS issue |
115 |
| - origin: ["http://localhost:4001"], |
116 |
| - credentials: true, |
117 |
| - }, |
118 |
| - }) |
| 124 | +1. **DevTools Connection** |
119 | 125 |
|
120 |
| - socketHandle({ io }) |
| 126 | + - Look for "Connected" status in the top-left corner of the DevTools app |
| 127 | + - If it shows "Disconnected", restart the DevTools app |
121 | 128 |
|
122 |
| - io.on("connection", client => { |
123 |
| - console.log(`'${client.handshake.query.username}' connected`) |
124 |
| - }) |
125 |
| -}) |
126 |
| -``` |
| 129 | +2. **No Devices Appearing** |
127 | 130 |
|
128 |
| -### React Query Dev Tools Server |
129 |
| - |
130 |
| -- Incorporate the ExternalDevTools component within any React.JS ready server |
131 |
| -- **Basic react-vite server example** _(we suppose here that the port is 4001)_: |
132 |
| - |
133 |
| -```javascript |
134 |
| -import React from "react" |
135 |
| -import ReactDOM from "react-dom/client" |
136 |
| -import { ExternalDevTools } from "react-query-external-dash" |
137 |
| - |
138 |
| -ReactDOM.createRoot(document.getElementById("root")!).render( |
139 |
| - <React.StrictMode> |
140 |
| - <ExternalDevTools |
141 |
| - socketURL={"http://localhost:4000"} |
142 |
| - query={{ |
143 |
| - clientType: "server", |
144 |
| - username: "Admin", |
145 |
| - userType: "admin", |
146 |
| - }} |
147 |
| - /> |
148 |
| - </React.StrictMode>, |
149 |
| -) |
150 |
| -``` |
| 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 |
151 | 135 |
|
152 |
| -## Ready to use Docker image |
| 136 | +3. **Data Not Syncing** |
| 137 | + - Confirm you're passing the correct `queryClient` instance |
| 138 | + - Set `enableLogs: true` to see connection information |
153 | 139 |
|
154 |
| -If you don't want to setup both Socket.IO + Dedicated React.js server to monitor your app, a Docker image is available to launch those both services at once, with custom ports and CORS urls. |
| 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. |
155 | 141 |
|
156 |
| -### 1. Image link |
| 142 | +## ⚠️ Important Note About Device IDs |
157 | 143 |
|
158 |
| -https://hub.docker.com/repository/docker/navalex/rq_devtool |
| 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. |
159 | 145 |
|
160 |
| -### 2. Environment variables |
| 146 | +**Recommended approaches:** |
161 | 147 |
|
162 |
| -- `SOCKET_PORT`: Port for the Socket.io server |
163 |
| -- `DT_PORT`: Port for the Vite server to access your devtool |
164 |
| -- `CORS_ORIGINS`: String to specify authorized url's for CORS in form of: "url1,url2,url3,..." (separate with coma without spaces). **Note that the devtool url is automaticly included in the CORS Policy.** |
| 148 | +```jsx |
| 149 | +// Simple approach for single devices |
| 150 | +deviceId: Platform.OS, // Works if you only have one device per platform |
165 | 151 |
|
166 |
| -### 3. Docker Compose example |
| 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); |
167 | 155 |
|
168 |
| -- You'll also need to open both ports to use this image. We suggest to define those in environment variables. |
| 156 | +useEffect(() => { |
| 157 | + const loadOrCreateDeviceId = async () => { |
| 158 | + // Try to load existing ID |
| 159 | + const storedId = await AsyncStorage.getItem('deviceId'); |
169 | 160 |
|
170 |
| -```yaml |
171 |
| -services: |
172 |
| - rqDevtools: |
173 |
| - image: navalex/rq_devtool:latest |
174 |
| - ports: |
175 |
| - - ${RQ_DEVTOOLS_PORT}:${RQ_DEVTOOLS_PORT} |
176 |
| - - ${RQ_DEVTOOLS_SOCKET_PORT}:${RQ_DEVTOOLS_SOCKET_PORT} |
177 |
| - environment: |
178 |
| - DT_PORT: ${RQ_DEVTOOLS_PORT} |
179 |
| - SOCKET_PORT: ${RQ_DEVTOOLS_SOCKET_PORT} |
180 |
| - SOCKET_CORS: "http://localhost:8102,http://localhost:5173" |
| 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 | +}, []); |
181 | 173 | ```
|
182 | 174 |
|
183 |
| -## Contribution |
| 175 | +## 📄 License |
| 176 | + |
| 177 | +MIT |
184 | 178 |
|
185 |
| -I welcome contributions, feedback, and bug reports. Feel free to open an issue or pull request on this GitHub repository. |
| 179 | +--- |
186 | 180 |
|
187 |
| -<br> |
188 |
| -<hr> |
189 |
| -<br> |
| 181 | +Made with ❤️ by [LovesWorking](https://github.com/LovesWorking) |
0 commit comments