From aa4cac38b0d769438c6cbb0c49c5ca4d97be44d0 Mon Sep 17 00:00:00 2001 From: Ilko Kacharov Date: Wed, 7 Jul 2021 01:51:44 +0300 Subject: [PATCH] Pass selection options to useRealtme hook (#21) * 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 --- .../documentation/realtime/use-realtime.md | 28 ++++++++++++++++++- src/hooks/realtime/use-realtime.ts | 11 ++++++-- .../__snapshots__/use-realtime.test.tsx.snap | 2 ++ test/hooks/realtime/use-realtime.test.tsx | 14 ++++++++++ 4 files changed, 51 insertions(+), 4 deletions(-) diff --git a/docs/pages/documentation/realtime/use-realtime.md b/docs/pages/documentation/realtime/use-realtime.md index 3e664f4..e79d706 100644 --- a/docs/pages/documentation/realtime/use-realtime.md +++ b/docs/pages/documentation/realtime/use-realtime.md @@ -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, ) diff --git a/src/hooks/realtime/use-realtime.ts b/src/hooks/realtime/use-realtime.ts index 2ae37bc..f20d409 100644 --- a/src/hooks/realtime/use-realtime.ts +++ b/src/hooks/realtime/use-realtime.ts @@ -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 = Omit< @@ -23,6 +23,10 @@ export type UseRealtimeAction = | { type: 'FETCH'; payload: UseSelectState } | { type: 'SUBSCRIPTION'; payload: SupabaseRealtimePayload } +export type UseRealtimeConfig = { + select?: Omit, 'pause'> +} + export type UseRealtimeCompareFn = ( data: Data, payload: Data, @@ -32,6 +36,7 @@ type CompareFnDefaultData = Data & { id: any } export function useRealtime( table: string, + config?: UseRealtimeConfig, compareFn: UseRealtimeCompareFn = (a, b) => (>a).id === (>b).id, @@ -41,7 +46,7 @@ export function useRealtime( 'Must specify table or row. Cannot listen for all database changes.', ) - const [result, reexecute] = useSelect(table) + const [result, reexecute] = useSelect(table, config?.select) const [state, dispatch] = useReducer< React.Reducer, UseRealtimeAction> >(reducer(compareFn), result) @@ -58,7 +63,7 @@ export function useRealtime( } const reducer = - (compareFn: UseRealtimeCompareFn) => + (compareFn: UseRealtimeCompareFn) => ( state: UseRealtimeState, action: UseRealtimeAction, diff --git a/test/hooks/realtime/__snapshots__/use-realtime.test.tsx.snap b/test/hooks/realtime/__snapshots__/use-realtime.test.tsx.snap index cd35a0e..9e4d133 100644 --- a/test/hooks/realtime/__snapshots__/use-realtime.test.tsx.snap +++ b/test/hooks/realtime/__snapshots__/use-realtime.test.tsx.snap @@ -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."`; diff --git a/test/hooks/realtime/use-realtime.test.tsx b/test/hooks/realtime/use-realtime.test.tsx index 3d6da9c..a593caf 100644 --- a/test/hooks/realtime/use-realtime.test.tsx +++ b/test/hooks/realtime/use-realtime.test.tsx @@ -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() + }) })