Skip to content

Commit

Permalink
Pass selection options to useRealtme hook (#21)
Browse files Browse the repository at this point in the history
* feat: added select options to useSubscription

* feat: pass type to compare fn

* test: added tests to cover new args

* docs: update example

* ci: update size (#23)

* feat: update useRealtime args

* feat: add default type

* docs: highlight correct row

Co-authored-by: Tom Meagher <tom@meagher.co>
  • Loading branch information
kachar and tmm authored Jul 6, 2021
1 parent d908b34 commit aa4cac3
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 4 deletions.
28 changes: 27 additions & 1 deletion docs/pages/documentation/realtime/use-realtime.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,38 @@ You can pass a function for comparing subscription event changes. By default, th

When using your own compare function, you typically want to compare unique values:

```tsx highlight=6
```tsx highlight=7
import { useRealtime } from 'react-supabase'

function Page() {
const [result, reexecute] = useRealtime(
'todos',
{ select: { columns:'id, username' } },
(data, payload) => data.username === payload.username,
)

return ...
}
```

## Initial selection of records

When initializing the component you might need to filter your data appropriately. You can pass the options directly to the `useSelect` hook.

First argument can be either a `string` table name or `useSelect` options with table property.

```tsx highlight=7,8,9,10
import { useRealtime } from 'react-supabase'

function Page() {
const [result, reexecute] = useRealtime(
'todos',
{
select: {
columns: 'id, username, description',
filter: (query) => query.eq('completed', false),
}
},
(data, payload) => data.username === payload.username,
)

Expand Down
11 changes: 8 additions & 3 deletions src/hooks/realtime/use-realtime.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useEffect, useReducer } from 'react'
import { SupabaseRealtimePayload } from '@supabase/supabase-js'

import { UseSelectState, useSelect } from '../data'
import { UseSelectConfig, UseSelectState, useSelect } from '../data'
import { useSubscription } from './use-subscription'

export type UseRealtimeState<Data = any> = Omit<
Expand All @@ -23,6 +23,10 @@ export type UseRealtimeAction<Data = any> =
| { type: 'FETCH'; payload: UseSelectState<Data> }
| { type: 'SUBSCRIPTION'; payload: SupabaseRealtimePayload<Data> }

export type UseRealtimeConfig<Data = any> = {
select?: Omit<UseSelectConfig<Data>, 'pause'>
}

export type UseRealtimeCompareFn<Data = any> = (
data: Data,
payload: Data,
Expand All @@ -32,6 +36,7 @@ type CompareFnDefaultData<Data> = Data & { id: any }

export function useRealtime<Data = any>(
table: string,
config?: UseRealtimeConfig<Data>,
compareFn: UseRealtimeCompareFn<Data> = (a, b) =>
(<CompareFnDefaultData<Data>>a).id ===
(<CompareFnDefaultData<Data>>b).id,
Expand All @@ -41,7 +46,7 @@ export function useRealtime<Data = any>(
'Must specify table or row. Cannot listen for all database changes.',
)

const [result, reexecute] = useSelect<Data>(table)
const [result, reexecute] = useSelect<Data>(table, config?.select)
const [state, dispatch] = useReducer<
React.Reducer<UseRealtimeState<Data>, UseRealtimeAction<Data>>
>(reducer(compareFn), result)
Expand All @@ -58,7 +63,7 @@ export function useRealtime<Data = any>(
}

const reducer =
<Data = any>(compareFn: UseRealtimeCompareFn) =>
<Data = any>(compareFn: UseRealtimeCompareFn<Data>) =>
(
state: UseRealtimeState<Data>,
action: UseRealtimeAction<Data>,
Expand Down
2 changes: 2 additions & 0 deletions test/hooks/realtime/__snapshots__/use-realtime.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@
exports[`useRealtime should throw when not inside Provider 1`] = `"No client has been specified using Provider."`;

exports[`useRealtime should throw when trying to listen all database changes 1`] = `"Must specify table or row. Cannot listen for all database changes."`;

exports[`useRealtime should throw when trying to listen all database changes via options 1`] = `"Must specify table or row. Cannot listen for all database changes."`;
14 changes: 14 additions & 0 deletions test/hooks/realtime/use-realtime.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,18 @@ describe('useRealtime', () => {
const { result } = renderHook(() => useRealtime('*'), { wrapper })
expect(() => result.current).toThrowErrorMatchingSnapshot()
})

it('should throw when trying to listen all database changes via options', () => {
const { result } = renderHook(
() =>
useRealtime('*', {
select: {
columns: 'id, username, completed',
filter: (query) => query.eq('completed', false),
},
}),
{ wrapper },
)
expect(() => result.current).toThrowErrorMatchingSnapshot()
})
})

1 comment on commit aa4cac3

@vercel
Copy link

@vercel vercel bot commented on aa4cac3 Jul 6, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.