@osdk/react 0.8.0 → 0.9.0-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/AGENTS.md +253 -0
  2. package/CHANGELOG.md +105 -24
  3. package/build/browser/intellisense.test.helpers/useOsdkObjectsWithProperties.js +1 -1
  4. package/build/browser/intellisense.test.helpers/useOsdkObjectsWithProperties.js.map +1 -1
  5. package/build/browser/intellisense.test.js +1 -1
  6. package/build/browser/intellisense.test.js.map +1 -1
  7. package/build/browser/new/platform-apis/admin/useCurrentFoundryUser.js +44 -0
  8. package/build/browser/new/platform-apis/admin/useCurrentFoundryUser.js.map +1 -0
  9. package/build/browser/new/platform-apis/admin/useFoundryUser.js +50 -0
  10. package/build/browser/new/platform-apis/admin/useFoundryUser.js.map +1 -0
  11. package/build/browser/new/platform-apis/admin/useFoundryUsersList.js +54 -0
  12. package/build/browser/new/platform-apis/admin/useFoundryUsersList.js.map +1 -0
  13. package/build/browser/new/useLinks.js +15 -8
  14. package/build/browser/new/useLinks.js.map +1 -1
  15. package/build/browser/new/useObjectSet.js +3 -2
  16. package/build/browser/new/useObjectSet.js.map +1 -1
  17. package/build/browser/new/useOsdkAction.js.map +1 -1
  18. package/build/browser/new/useOsdkAggregation.js +1 -1
  19. package/build/browser/new/useOsdkAggregation.js.map +1 -1
  20. package/build/browser/new/useOsdkFunction.js +101 -0
  21. package/build/browser/new/useOsdkFunction.js.map +1 -0
  22. package/build/browser/new/useOsdkObject.js +1 -1
  23. package/build/browser/new/useOsdkObject.js.map +1 -1
  24. package/build/browser/new/useOsdkObjects.js +4 -3
  25. package/build/browser/new/useOsdkObjects.js.map +1 -1
  26. package/build/browser/public/experimental.js +4 -0
  27. package/build/browser/public/experimental.js.map +1 -1
  28. package/build/browser/utils/usePlatformQuery.js +74 -0
  29. package/build/browser/utils/usePlatformQuery.js.map +1 -0
  30. package/build/cjs/{chunk-OVBG5VXE.cjs → chunk-V32JHU3O.cjs} +8 -3
  31. package/build/cjs/chunk-V32JHU3O.cjs.map +1 -0
  32. package/build/cjs/index.cjs +4 -4
  33. package/build/cjs/public/experimental.cjs +399 -66
  34. package/build/cjs/public/experimental.cjs.map +1 -1
  35. package/build/cjs/public/experimental.d.cts +279 -32
  36. package/build/esm/intellisense.test.helpers/useOsdkObjectsWithProperties.js +1 -1
  37. package/build/esm/intellisense.test.helpers/useOsdkObjectsWithProperties.js.map +1 -1
  38. package/build/esm/intellisense.test.js +1 -1
  39. package/build/esm/intellisense.test.js.map +1 -1
  40. package/build/esm/new/platform-apis/admin/useCurrentFoundryUser.js +44 -0
  41. package/build/esm/new/platform-apis/admin/useCurrentFoundryUser.js.map +1 -0
  42. package/build/esm/new/platform-apis/admin/useFoundryUser.js +50 -0
  43. package/build/esm/new/platform-apis/admin/useFoundryUser.js.map +1 -0
  44. package/build/esm/new/platform-apis/admin/useFoundryUsersList.js +54 -0
  45. package/build/esm/new/platform-apis/admin/useFoundryUsersList.js.map +1 -0
  46. package/build/esm/new/useLinks.js +15 -8
  47. package/build/esm/new/useLinks.js.map +1 -1
  48. package/build/esm/new/useObjectSet.js +3 -2
  49. package/build/esm/new/useObjectSet.js.map +1 -1
  50. package/build/esm/new/useOsdkAction.js.map +1 -1
  51. package/build/esm/new/useOsdkAggregation.js +1 -1
  52. package/build/esm/new/useOsdkAggregation.js.map +1 -1
  53. package/build/esm/new/useOsdkFunction.js +101 -0
  54. package/build/esm/new/useOsdkFunction.js.map +1 -0
  55. package/build/esm/new/useOsdkObject.js +1 -1
  56. package/build/esm/new/useOsdkObject.js.map +1 -1
  57. package/build/esm/new/useOsdkObjects.js +4 -3
  58. package/build/esm/new/useOsdkObjects.js.map +1 -1
  59. package/build/esm/public/experimental.js +4 -0
  60. package/build/esm/public/experimental.js.map +1 -1
  61. package/build/esm/utils/usePlatformQuery.js +74 -0
  62. package/build/esm/utils/usePlatformQuery.js.map +1 -0
  63. package/build/types/new/platform-apis/admin/useCurrentFoundryUser.d.ts +28 -0
  64. package/build/types/new/platform-apis/admin/useCurrentFoundryUser.d.ts.map +1 -0
  65. package/build/types/new/platform-apis/admin/useFoundryUser.d.ts +36 -0
  66. package/build/types/new/platform-apis/admin/useFoundryUser.d.ts.map +1 -0
  67. package/build/types/new/platform-apis/admin/useFoundryUsersList.d.ts +52 -0
  68. package/build/types/new/platform-apis/admin/useFoundryUsersList.d.ts.map +1 -0
  69. package/build/types/new/useLinks.d.ts +5 -5
  70. package/build/types/new/useLinks.d.ts.map +1 -1
  71. package/build/types/new/useObjectSet.d.ts +4 -0
  72. package/build/types/new/useObjectSet.d.ts.map +1 -1
  73. package/build/types/new/useOsdkAction.d.ts +3 -3
  74. package/build/types/new/useOsdkAction.d.ts.map +1 -1
  75. package/build/types/new/useOsdkAggregation.d.ts +10 -12
  76. package/build/types/new/useOsdkAggregation.d.ts.map +1 -1
  77. package/build/types/new/useOsdkFunction.d.ts +112 -0
  78. package/build/types/new/useOsdkFunction.d.ts.map +1 -0
  79. package/build/types/new/useOsdkObjects.d.ts +31 -13
  80. package/build/types/new/useOsdkObjects.d.ts.map +1 -1
  81. package/build/types/public/experimental.d.ts +5 -0
  82. package/build/types/public/experimental.d.ts.map +1 -1
  83. package/build/types/utils/usePlatformQuery.d.ts +25 -0
  84. package/build/types/utils/usePlatformQuery.d.ts.map +1 -0
  85. package/docs/actions.md +414 -0
  86. package/docs/advanced-queries.md +663 -0
  87. package/docs/cache-management.md +213 -0
  88. package/docs/getting-started.md +382 -0
  89. package/docs/platform-apis.md +203 -0
  90. package/docs/querying-data.md +648 -0
  91. package/package.json +10 -6
  92. package/build/browser/new/types.js +0 -2
  93. package/build/browser/new/types.js.map +0 -1
  94. package/build/cjs/chunk-OVBG5VXE.cjs.map +0 -1
  95. package/build/esm/new/types.js +0 -2
  96. package/build/esm/new/types.js.map +0 -1
  97. package/build/types/new/types.d.ts +0 -5
  98. package/build/types/new/types.d.ts.map +0 -1
@@ -0,0 +1,213 @@
1
+ ---
2
+ sidebar_position: 5
3
+ ---
4
+
5
+ # Cache Management
6
+
7
+ This guide covers how the OSDK React cache system works and how to manually control it.
8
+
9
+ ## How the Cache Works
10
+
11
+ The `OsdkProvider2` creates an `ObservableClient` that maintains a normalized cache of all queries and their results.
12
+
13
+ ### What Gets Cached
14
+
15
+ | Data Type | Cache Key Based On |
16
+ |-----------|-------------------|
17
+ | **Objects** | Object type + primary key |
18
+ | **Lists** | Object type + where clause + orderBy |
19
+ | **Links** | Source object + link name + filters |
20
+ | **Aggregations** | Object type + where clause + aggregate definition |
21
+
22
+ ### Cache Sharing
23
+
24
+ - **Same query = same cache entry**: Two components calling `useOsdkObjects(Todo, { where: { isComplete: false } })` share the same cached result
25
+ - **Different filters = different entries**: `{ isComplete: false }` and `{ isComplete: true }` create separate cache entries
26
+ - **Derived properties create variants**: Adding `withProperties` creates a separate cache entry
27
+
28
+ ### Object Normalization
29
+
30
+ Objects are stored once and shared across all queries that reference them:
31
+
32
+ ```
33
+ useOsdkObjects(Todo) ─┐
34
+ ├─► Todo:1 (single cached instance)
35
+ useOsdkObject(Todo, "1") ─┘
36
+ ```
37
+
38
+ When `Todo:1` is updated, all queries referencing it see the change immediately.
39
+
40
+ ## Automatic Cache Updates
41
+
42
+ ### After Actions
43
+
44
+ When an action completes, the server response specifies which objects were affected:
45
+
46
+ - **Added objects**: Fetched and added to cache, relevant lists re-evaluated
47
+ - **Modified objects**: Re-fetched, all queries containing them updated
48
+ - **Deleted objects**: Removed from cache and all lists
49
+
50
+ ### Optimistic Updates
51
+
52
+ With `$optimisticUpdate`:
53
+
54
+ 1. Optimistic layer created with your changes
55
+ 2. UI shows optimistic state (`isOptimistic: true`)
56
+ 3. On success: Server data replaces optimistic layer
57
+ 4. On failure: Optimistic layer removed, original state restored
58
+
59
+ ### Real-time Updates
60
+
61
+ With `streamUpdates: true`, the cache receives WebSocket updates and applies them automatically.
62
+
63
+ ## When Manual Invalidation is Needed
64
+
65
+ Automatic updates don't cover:
66
+
67
+ - Data changed by an external system or external cache
68
+ - Data modified outside OSDK (direct API calls, background jobs)
69
+
70
+ ## Manual Cache Invalidation
71
+
72
+ The `ObservableClient` provides methods to manually invalidate cached data.
73
+
74
+ ### Setup
75
+
76
+ To use invalidation methods, create an `ObservableClient` and pass it to `OsdkProvider2`:
77
+
78
+ ```tsx
79
+ // client.ts
80
+ import { createClient } from "@osdk/client";
81
+ import {
82
+ createObservableClient,
83
+ type ObservableClient,
84
+ } from "@osdk/client/unstable-do-not-use";
85
+
86
+ const client = createClient(
87
+ "https://your-stack.palantirfoundry.com",
88
+ "your-ontology-rid",
89
+ authProvider,
90
+ );
91
+
92
+ // Create and export the observable client for invalidation
93
+ export const observableClient = createObservableClient(client);
94
+ export { client };
95
+ ```
96
+
97
+ ```tsx
98
+ // main.tsx
99
+ import { OsdkProvider2 } from "@osdk/react/experimental";
100
+ import { client, observableClient } from "./client";
101
+
102
+ ReactDOM.createRoot(document.getElementById("root")!).render(
103
+ <OsdkProvider2 client={client} observableClient={observableClient}>
104
+ <App />
105
+ </OsdkProvider2>,
106
+ );
107
+ ```
108
+
109
+ ### Invalidation Methods
110
+
111
+ #### Object Invalidation
112
+
113
+ | Method | Effect | Use Case |
114
+ |--------|--------|----------|
115
+ | `invalidateObjects([obj1, obj2])` | Re-fetches specific objects | You know exactly which objects are stale |
116
+ | `invalidateObjectType(Todo)` | Re-fetches all objects and lists of that type | External bulk update |
117
+ | `invalidateAll()` | Re-fetches everything | Last resort |
118
+
119
+ #### Function Invalidation
120
+
121
+ | Method | Effect | Use Case |
122
+ |--------|--------|----------|
123
+ | `invalidateFunction(queryDef, params)` | Re-fetches a specific function query | You know which function call is stale |
124
+ | `invalidateFunction(queryDef)` | Re-fetches ALL queries for that function | External change affecting all calls |
125
+ | `invalidateFunctionsByObject(apiName, pk)` | Re-fetches functions depending on a specific object | Object changed outside action flow |
126
+
127
+ ### Usage
128
+
129
+ ```tsx
130
+ import { Todo, getEmployeeMetrics } from "@my/osdk";
131
+ import { observableClient } from "./client";
132
+
133
+ // Invalidate specific objects
134
+ await observableClient.invalidateObjects([todo1, todo2]);
135
+
136
+ // Invalidate all data for a type
137
+ await observableClient.invalidateObjectType(Todo);
138
+
139
+ // Invalidate a specific function query
140
+ await observableClient.invalidateFunction(getEmployeeMetrics, { departmentId: "sales" });
141
+
142
+ // Invalidate ALL queries for a function
143
+ await observableClient.invalidateFunction(getEmployeeMetrics);
144
+
145
+ // Invalidate functions that depend on a specific object instance
146
+ // (functions called with dependsOnObjects containing this object)
147
+ await observableClient.invalidateFunctionsByObject("Employee", "emp-123");
148
+
149
+ // Invalidate everything (use sparingly)
150
+ await observableClient.invalidateAll();
151
+ ```
152
+
153
+ ### Type Isolation
154
+
155
+ `invalidateObjectType(Todo)` only affects Todo-related data:
156
+
157
+ - Re-fetches all Todo objects
158
+ - Re-fetches all Todo lists
159
+ - Re-fetches links where Todo is the source type
160
+ - Does NOT affect other object types, even if linked to Todos
161
+
162
+ ### Function Invalidation Details
163
+
164
+ `invalidateFunctionsByObject(apiName, primaryKey)` invalidates function queries that were registered with `dependsOnObjects` containing the specified object:
165
+
166
+ ```tsx
167
+ // If useOsdkFunction was called with:
168
+ const { data } = useOsdkFunction(getEmployeeReport, {
169
+ params: { employeeId: employee.$primaryKey },
170
+ dependsOnObjects: [employee],
171
+ });
172
+
173
+ // You can invalidate it by calling:
174
+ await observableClient.invalidateFunctionsByObject("Employee", employee.$primaryKey);
175
+ ```
176
+
177
+ This is useful when you know a specific object has changed outside of the normal action flow.
178
+
179
+ ## Cache with Optimistic Updates
180
+
181
+ ```tsx
182
+ import { $Actions, Todo } from "@my/osdk";
183
+ import { useOsdkAction, useOsdkObject } from "@osdk/react/experimental";
184
+
185
+ function TodoView({ todo }: { todo: Todo.OsdkInstance }) {
186
+ const { isOptimistic } = useOsdkObject(todo);
187
+ const { applyAction } = useOsdkAction($Actions.completeTodo);
188
+
189
+ const handleComplete = () => {
190
+ applyAction({
191
+ todo,
192
+ isComplete: true,
193
+ $optimisticUpdate: (ou) => {
194
+ ou.updateObject(todo.$clone({ isComplete: true }));
195
+ },
196
+ });
197
+ };
198
+
199
+ return (
200
+ <div>
201
+ {todo.title}
202
+ {isOptimistic && " (Saving...)"}
203
+ <button onClick={handleComplete}>Complete</button>
204
+ </div>
205
+ );
206
+ }
207
+ ```
208
+
209
+ ## Best Practices
210
+
211
+ 1. **Be specific**: Use `invalidateObjects` when you know what data specifically changed
212
+ 2. **Use type-level invalidation**: `invalidateObjectType` for external bulk changes
213
+ 3. **Avoid multiple sources of truth**: Coordinating side effects between multiple systems is tricky; we recommend solely using the OSDK React cache when possible for data loading
@@ -0,0 +1,382 @@
1
+ ---
2
+ sidebar_position: 1
3
+ ---
4
+
5
+ # Getting Started
6
+
7
+ This guide covers installation, setup, and your first OSDK React application.
8
+
9
+ :::info Beta Release
10
+ `@osdk/react` is currently in beta. While the package is suitable for production use, you may encounter minor bugs as we continue development. We welcome bug reports and feedback.
11
+ :::
12
+
13
+ ## Installation
14
+
15
+ ### 1. Install Beta Packages
16
+
17
+ Using `latest` doesn't always install actual latest versions for beta packages. Specify them explicitly.
18
+
19
+ :::warning Version Compatibility
20
+ All `@osdk/*` packages must use **compatible versions**. Mismatched versions (e.g., mixing an old `@osdk/client` with a newer `@osdk/react`) will cause TypeScript errors.
21
+ :::
22
+
23
+ ```json
24
+ {
25
+ "dependencies": {
26
+ "@osdk/api": "^2.7.0-beta.8",
27
+ "@osdk/client": "^2.7.0-beta.8",
28
+ "@osdk/react": "^0.9.0-beta.5"
29
+ }
30
+ }
31
+ ```
32
+
33
+ Or install via command line:
34
+
35
+ ```bash
36
+ npm install @osdk/api @osdk/client @osdk/react
37
+ ```
38
+
39
+ Check for newer versions on npm:
40
+
41
+ - [@osdk/react versions](https://www.npmjs.com/package/@osdk/react?activeTab=versions)
42
+ - [@osdk/client versions](https://www.npmjs.com/package/@osdk/client?activeTab=versions)
43
+ - [@osdk/api versions](https://www.npmjs.com/package/@osdk/api?activeTab=versions)
44
+
45
+ ### 2. Generate Your SDK with Beta Features
46
+
47
+ If you haven't generated an SDK yet:
48
+
49
+ 1. Open Developer Console for your Foundry
50
+ 2. Click "SDK versions" tab (tag icon in left navbar)
51
+ 3. Click "Settings" → enable beta features for TypeScript
52
+ 4. Click "Generate new version" → check "npm" checkbox → select latest `-beta` generator
53
+ 5. Add the generated SDK to your package.json:
54
+
55
+ ```json
56
+ {
57
+ "dependencies": {
58
+ "@your-app/sdk": "^0.4.0"
59
+ }
60
+ }
61
+ ```
62
+
63
+ ## Provider Setup
64
+
65
+ ### Stable vs Experimental
66
+
67
+ `@osdk/react` has two entry points:
68
+
69
+ | | `@osdk/react` | `@osdk/react/experimental` |
70
+ | ----------------- | --------------------------- | --------------------------------------------- |
71
+ | **Use when** | You only need client access | You want reactive data hooks (most apps) |
72
+ | **Features** | Client provider, metadata | Queries, actions, caching, optimistic updates |
73
+ | **API stability** | Stable | APIs may change between releases |
74
+
75
+ **We recommend starting with experimental.** The "experimental" label indicates the API surface may evolve, not that the features are unstable or buggy. Most applications benefit from the reactive hooks, automatic caching, and optimistic update support.
76
+
77
+ ### Stable Features (`@osdk/react`)
78
+
79
+ For basic client access only:
80
+
81
+ ```tsx
82
+ import { OsdkProvider } from "@osdk/react";
83
+ import client from "./client";
84
+
85
+ ReactDOM.createRoot(document.getElementById("root")!).render(
86
+ <OsdkProvider client={client}>
87
+ <App />
88
+ </OsdkProvider>,
89
+ );
90
+ ```
91
+
92
+ Stable exports (use with `OsdkProvider`):
93
+
94
+ - `OsdkProvider` - Provider component for basic client access
95
+ - `useOsdkClient` - Access the OSDK client directly
96
+ - `useOsdkMetadata` - Fetch type metadata
97
+
98
+ :::note
99
+ `useOsdkClient` and `useOsdkMetadata` are available from both `@osdk/react` (stable) and `@osdk/react/experimental`. When using experimental features with `OsdkProvider2`, import from `@osdk/react/experimental` for consistency.
100
+ :::
101
+
102
+ ### Experimental Features (`@osdk/react/experimental`)
103
+
104
+ For reactive data management, cache, and optimistic updates.
105
+
106
+ :::tip About Experimental Hooks
107
+ The hooks in `@osdk/react/experimental` are production-ready and recommended for new projects. They are labeled "experimental" because they represent a newer architecture that is under active development. Once stabilized, these hooks will be promoted to the main `@osdk/react` package.
108
+ :::
109
+
110
+ ```tsx
111
+ import { OsdkProvider2 } from "@osdk/react/experimental";
112
+ import client from "./client";
113
+
114
+ ReactDOM.createRoot(document.getElementById("root")!).render(
115
+ <OsdkProvider2 client={client}>
116
+ <App />
117
+ </OsdkProvider2>,
118
+ );
119
+ ```
120
+
121
+ **All experimental hooks require `OsdkProvider2` at your app root.**
122
+
123
+ Experimental exports:
124
+
125
+ - `OsdkProvider2` - Provider for experimental features
126
+ - `useOsdkObjects` - Query collections of objects
127
+ - `useOsdkObject` - Query single objects
128
+ - `useOsdkAction` - Execute and validate actions
129
+ - `useLinks` - Navigate object relationships
130
+ - `useObjectSet` - Advanced queries with set operations
131
+ - `useOsdkAggregation` - Server-side aggregations
132
+ - `useOsdkFunction` - Execute and observe OSDK functions
133
+ - `useDebouncedCallback` - Debounce callbacks
134
+ - `useOsdkClient` - Access the OSDK client
135
+ - `useOsdkMetadata` - Fetch type metadata (also available from stable)
136
+
137
+ ## Quick Start Checklist
138
+
139
+ Before using experimental hooks:
140
+
141
+ - [ ] App wrapped in `<OsdkProvider2 client={client}>`
142
+ - [ ] OsdkProvider2 at app root (not nested inside components)
143
+ - [ ] Passing configured OSDK client to OsdkProvider2
144
+ - [ ] All components using experimental hooks inside the provider
145
+
146
+ ## First Query
147
+
148
+ :::note About `@my/osdk`
149
+ Throughout this documentation, `@my/osdk` refers to **your generated SDK package**. This is created when you generate an SDK in Foundry Developer Console (step 2 above). Replace `@my/osdk` with your actual package name (e.g., `@your-app/sdk`).
150
+ :::
151
+
152
+ ```tsx
153
+ import { Todo } from "@my/osdk";
154
+ import { useOsdkObjects } from "@osdk/react/experimental";
155
+
156
+ function TodoList() {
157
+ const { data, isLoading, error } = useOsdkObjects(Todo, {
158
+ where: { isComplete: false },
159
+ orderBy: { createdAt: "desc" },
160
+ });
161
+
162
+ if (!data && isLoading) {
163
+ return <div>Loading...</div>;
164
+ }
165
+
166
+ if (error) {
167
+ return <div>Error: {JSON.stringify(error)}</div>;
168
+ }
169
+
170
+ return (
171
+ <div>
172
+ {data?.map(todo => <div key={todo.$primaryKey}>{todo.title}</div>)}
173
+ </div>
174
+ );
175
+ }
176
+ ```
177
+
178
+ See [Querying Data](/react/querying-data) for filtering, pagination, real-time updates, and more.
179
+
180
+ ## First Action
181
+
182
+ ```tsx
183
+ import { $Actions, Todo } from "@my/osdk";
184
+ import { useOsdkAction } from "@osdk/react/experimental";
185
+
186
+ function CompleteTodoButton({ todo }: { todo: Todo.OsdkInstance }) {
187
+ const { applyAction, isPending, error } = useOsdkAction(
188
+ $Actions.completeTodo,
189
+ );
190
+
191
+ const handleClick = () => {
192
+ applyAction({ todo, isComplete: true });
193
+ };
194
+
195
+ return (
196
+ <div>
197
+ <button onClick={handleClick} disabled={isPending}>
198
+ {isPending ? "Saving..." : "Complete"}
199
+ </button>
200
+ {error && <div>Error: {JSON.stringify(error)}</div>}
201
+ </div>
202
+ );
203
+ }
204
+ ```
205
+
206
+ See [Actions](/react/actions) for validation, batch actions, and optimistic updates.
207
+
208
+ ## Troubleshooting
209
+
210
+ ### "Property 'store' is missing" with OsdkProvider2
211
+
212
+ This error occurs when your `@osdk/client` version is incompatible with `@osdk/react`. The versions must match.
213
+
214
+ **Fix:** Ensure all `@osdk/*` packages use compatible beta versions:
215
+
216
+ 1. Go to **Developer Console** → **SDK versions** → **Settings**
217
+ 2. Enable **beta features** for TypeScript
218
+ 3. Generate a new SDK version with the latest beta generator
219
+ 4. Check the **Installation instructions** for the compatible `@osdk/client` version
220
+ 5. Update your package.json to use matching versions:
221
+
222
+ ```json
223
+ {
224
+ "dependencies": {
225
+ "@osdk/api": "^2.7.0-beta.8",
226
+ "@osdk/client": "^2.7.0-beta.8",
227
+ "@osdk/react": "^0.9.0-beta.5"
228
+ }
229
+ }
230
+ ```
231
+
232
+ ### "Cannot read property 'observableClient' of undefined"
233
+
234
+ The component is outside `<OsdkProvider2>`. Move OsdkProvider2 higher in your component tree.
235
+
236
+ **Wrong:**
237
+
238
+ ```tsx
239
+ function App() {
240
+ return <TodoList />; // No OsdkProvider2!
241
+ }
242
+ ```
243
+
244
+ **Correct:**
245
+
246
+ ```tsx
247
+ ReactDOM.createRoot(document.getElementById("root")!).render(
248
+ <OsdkProvider2 client={client}>
249
+ <TodoList />
250
+ </OsdkProvider2>,
251
+ );
252
+ ```
253
+
254
+ ### Only some components work with hooks
255
+
256
+ OsdkProvider2 is not at the root.
257
+
258
+ **Wrong:**
259
+
260
+ ```tsx
261
+ function App() {
262
+ return (
263
+ <>
264
+ <Header /> {/* Can't use hooks */}
265
+ <OsdkProvider2 client={client}>
266
+ <Content /> {/* Only this can use hooks */}
267
+ </OsdkProvider2>
268
+ </>
269
+ );
270
+ }
271
+ ```
272
+
273
+ **Correct:**
274
+
275
+ ```tsx
276
+ ReactDOM.createRoot(document.getElementById("root")!).render(
277
+ <OsdkProvider2 client={client}>
278
+ <App /> {/* All components can use hooks */}
279
+ </OsdkProvider2>,
280
+ );
281
+ ```
282
+
283
+ ### Hooks return no data
284
+
285
+ Ensure you're passing the same client instance, not creating a new one:
286
+
287
+ **Wrong:**
288
+
289
+ ```tsx
290
+ <OsdkProvider2 client={createNewClient()}> {/* New instance each render */}
291
+ ```
292
+
293
+ **Correct:**
294
+
295
+ ```tsx
296
+ import client from "./client"; // Created once
297
+ <OsdkProvider2 client={client}>
298
+ ```
299
+
300
+ ### "Hooks cannot be conditionally called"
301
+
302
+ Use the `enabled` option instead of conditional hook calls:
303
+
304
+ **Wrong:**
305
+
306
+ ```tsx
307
+ if (shouldLoad) {
308
+ const { data } = useOsdkObjects(Todo); // Conditional hook!
309
+ }
310
+ ```
311
+
312
+ **Correct:**
313
+
314
+ ```tsx
315
+ const { data } = useOsdkObjects(Todo, {
316
+ enabled: shouldLoad,
317
+ });
318
+ ```
319
+
320
+ ## NPM Peer Dependency Issues
321
+
322
+ If NPM has trouble resolving peer dependencies with beta packages, add to package.json:
323
+
324
+ ```json
325
+ {
326
+ "overrides": {
327
+ "@osdk/client": "$@osdk/client",
328
+ "@osdk/react": "$@osdk/react"
329
+ }
330
+ }
331
+ ```
332
+
333
+ ## FAQ
334
+
335
+ ### When should I use `@osdk/react` vs React Query?
336
+
337
+ **Use `@osdk/react`** when your application primarily works with OSDK data:
338
+
339
+ - Querying Foundry objects and ontology data
340
+ - Executing actions on Foundry objects
341
+ - Taking advantage of automatic cache management for OSDK objects
342
+ - Real-time updates via WebSocket subscriptions
343
+
344
+ **Use React Query** when you need to make requests to third-party APIs or non-OSDK endpoints:
345
+
346
+ - External REST APIs
347
+ - GraphQL services not backed by Foundry
348
+ - Custom backend services
349
+
350
+ **You can use both together.** `@osdk/react` hooks work independently from React Query. For applications that mix OSDK data with external services, use `@osdk/react` for Foundry operations and React Query for external APIs.
351
+
352
+ ```tsx
353
+ import { Todo } from "@my/osdk";
354
+ import { useOsdkObjects } from "@osdk/react/experimental";
355
+ import { useQuery } from "@tanstack/react-query";
356
+
357
+ function Dashboard() {
358
+ // Use @osdk/react for Foundry data
359
+ const { data: todos } = useOsdkObjects(Todo);
360
+
361
+ // Use React Query for external APIs
362
+ const { data: weatherData } = useQuery({
363
+ queryKey: ["weather"],
364
+ queryFn: () => fetch("https://api.weather.com/current").then(r => r.json()),
365
+ });
366
+
367
+ return (
368
+ <div>
369
+ <TodoList todos={todos} />
370
+ <WeatherWidget data={weatherData} />
371
+ </div>
372
+ );
373
+ }
374
+ ```
375
+
376
+ ## Next Steps
377
+
378
+ - [Querying Data](/react/querying-data) - useOsdkObjects, useOsdkObject, useLinks, pagination, real-time updates
379
+ - [Actions](/react/actions) - useOsdkAction, validation, optimistic updates, debouncing
380
+ - [Advanced Queries](/react/advanced-queries) - useObjectSet, derived properties, aggregations
381
+ - [Cache Management](/react/cache-management) - Cache behavior and manual invalidation
382
+ - [Platform APIs](/react/platform-apis) - useCurrentFoundryUser, useFoundryUser, useFoundryUsersList