Skip to content

Commit 55290fc

Browse files
authored
Merge pull request #184 from gmercey/fix-155
fix #155 useFind hybrid limitation
2 parents 3693ded + 23aa62b commit 55290fc

1 file changed

Lines changed: 88 additions & 1 deletion

File tree

docs/services/use-find.md

Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,8 @@ troubleshoot reactivity.
8686
happens whenever a `created`, `updated`, or `removed` event is provided. This will potentially be refined in the
8787
future.
8888
- when set to `'hybrid'`, you get server-side pagination with live lists. This will likely become the default in
89-
the future.
89+
the future. **Important**: Hybrid pagination requires that your frontend and backend data structures match exactly.
90+
See [Hybrid Paging with Live Lists](#hybrid-paging-with-live-lists) for details and limitations.
9091
- **`pagination` {Object}** an object containing two refs: `$limit` and `$skip`. This allows you to synchronize the
9192
internally-controlled pagination with UI-bound `$limit` and `$skip` properties.
9293
- **`immediate` {boolean = true}** when `paginateOn: 'server'` is set, by default it will make an initial request. Set
@@ -227,3 +228,89 @@ await posts$.next()
227228
// move to the previous page
228229
await posts$.prev()
229230
```
231+
232+
### Hybrid Paging with Live Lists
233+
234+
Hybrid pagination combines server-side pagination with live-updating lists. It provides the best of both worlds by fetching paginated data from the server while maintaining reactive updates from real-time events.
235+
236+
```ts
237+
const { api } = useFeathers()
238+
239+
const params = computed(() => ({ query: { userId: 123 } }))
240+
const posts$ = api.service('posts').useFind(params, { paginateOn: 'hybrid' })
241+
242+
// move to the next page (fetches from server)
243+
await posts$.next()
244+
245+
// move to the previous page (fetches from server)
246+
await posts$.prev()
247+
```
248+
249+
#### Important Limitation: Data Structure Consistency
250+
251+
<BlockQuote type="warning">
252+
253+
**Hybrid pagination only works correctly when your frontend and backend data structures match exactly.** If your backend returns populated/joined data that differs from what's stored in your frontend service store, you may encounter issues where `useFind` returns only IDs or totals without the actual items.
254+
255+
</BlockQuote>
256+
257+
For example, if your backend returns:
258+
```ts
259+
// Backend response with populated user data
260+
{
261+
id: 1,
262+
title: 'My Post',
263+
user: { id: 5, name: 'John Doe' } // populated user object
264+
}
265+
```
266+
267+
But your frontend posts store expects:
268+
```ts
269+
// Frontend store expects simple user ID
270+
{
271+
id: 1,
272+
title: 'My Post',
273+
userId: 5 // simple user ID reference
274+
}
275+
```
276+
277+
In this case, hybrid pagination may not work as expected because the local store filtering cannot match the server response structure.
278+
279+
#### Workaround for Mismatched Data Structures
280+
281+
When your frontend and backend data structures don't match, use manual queries instead of `useFind` with hybrid pagination:
282+
283+
```ts
284+
const { api } = useFeathers()
285+
286+
// Manual approach for mismatched data structures
287+
const posts = ref([])
288+
const total = ref(0)
289+
const isPending = ref(false)
290+
291+
async function loadPosts(query = {}) {
292+
isPending.value = true
293+
try {
294+
// Fetch from server with your complex query/population
295+
const response = await api.service('posts').find({
296+
query: { ...query, $limit: 10 }
297+
})
298+
299+
// Transform and store the data as needed
300+
posts.value = response.data
301+
total.value = response.total
302+
303+
// Optionally, also query local store for additional filtering
304+
const localResults = api.service('posts').findInStore({
305+
query: { userId: response.data[0]?.userId }
306+
})
307+
} finally {
308+
isPending.value = false
309+
}
310+
}
311+
312+
// Use it
313+
await loadPosts({ userId: 123 })
314+
```
315+
316+
This approach gives you full control over data fetching and transformation while still allowing you to use `findInStore` for local querying when needed.

0 commit comments

Comments
 (0)