Skip to content

Commit

Permalink
feat(database): add converter option to useObjectValue hooks
Browse files Browse the repository at this point in the history
  • Loading branch information
andipaetzold committed Oct 17, 2021
1 parent 4aa9f66 commit 8cb8511
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 6 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@ const [objectValue, loading, error] = useObjectValue(query);
Params:

- `query`: Realtime Database query
- `options`: Options to configure how the object is fetched
- `converter`: Function to extract the desired data from the DataSnapshot. Similar to Firestore converters. Default: `snap.val()`.

Returns:

Expand All @@ -147,6 +149,8 @@ const [objectValue, loading, error] = useObjectValueOnce(query);
Params:

- `query`: Realtime Database query
- `options`: Options to configure how the object is fetched
- `converter`: Function to extract the desired data from the DataSnapshot. Similar to Firestore converters. Default: `snap.val()`.

Returns:

Expand Down
19 changes: 16 additions & 3 deletions src/database/useObjectValue.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,37 @@
import { onValue, Query } from "firebase/database";
import { DataSnapshot, onValue, Query } from "firebase/database";
import { useCallback } from "react";
import { ValueHookResult } from "../common";
import { useListen, UseListenOnChange } from "../internal/useListen";
import { isQueryEqual } from "./internal";

export type UseObjectValueResult<Value = unknown> = ValueHookResult<Value, Error>;

export type UseObjectValueConverter<Value> = (snap: DataSnapshot) => Value;

export interface UseObjectValueOptions<Value> {
converter?: UseObjectValueConverter<Value>;
}

/**
* Returns and updates the DataSnapshot of the Realtime Database query
*
* @template {Value} Type of the object value
* @param {Query | undefined | null} query Realtime Database query
* @param {?UseObjectValueOptions} options Options to configure how the object is fetched
* * `converter`: Function to extract the desired data from the DataSnapshot. Similar to Firestore converters. Default: `snap.val()`.
* @returns {UseObjectValueResult} User, loading state, and error
* * value: Object value; `undefined` if query is currently being fetched, or an error occurred
* * loading: `true` while fetching the query; `false` if the query was fetched successfully or an error occurred
* * error: `undefined` if no error occurred
*/
export function useObjectValue<Value = unknown>(query: Query | undefined | null): UseObjectValueResult<Value> {
export function useObjectValue<Value = unknown>(
query: Query | undefined | null,
options?: UseObjectValueOptions<Value>
): UseObjectValueResult<Value> {
const { converter = (snap: DataSnapshot) => snap.val() } = options ?? {};

const onChange: UseListenOnChange<Value, Error, Query> = useCallback(
(stableQuery, next, error) => onValue(stableQuery, (snap) => next(snap.val()), error),
(stableQuery, next, error) => onValue(stableQuery, (snap) => next(converter(snap)), error),
[]
);

Expand Down
20 changes: 17 additions & 3 deletions src/database/useObjectValueOnce.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,39 @@
import { get, Query } from "firebase/database";
import { DataSnapshot, get, Query } from "firebase/database";
import { useCallback } from "react";
import { ValueHookResult } from "../common";
import { useOnce } from "../internal/useOnce";
import { isQueryEqual } from "./internal";

export type UseObjectValueOnceResult<Value = unknown> = ValueHookResult<Value, Error>;

export type UseObjectValueOnceConverter<Value> = (snap: DataSnapshot) => Value;

export interface UseObjectValueOnceOptions<Value> {
converter?: UseObjectValueOnceConverter<Value>;
}

/**
* Returns the DataSnapshot of the Realtime Database query. Does not update the DataSnapshot once initially fetched
*
* @template {Value} Type of the object value
* @param {Query | undefined | null} query Realtime Database query
* @param {?UseObjectValueOnceOptions} options Options to configure how the object is fetched
* * `converter`: Function to extract the desired data from the DataSnapshot. Similar to Firestore converters. Default: `snap.val()`.
* @returns {UseObjectValueOnceResult} User, loading state, and error
* * value: Object value; `undefined` if query is currently being fetched, or an error occurred
* * loading: `true` while fetching the query; `false` if the query was fetched successfully or an error occurred
* * error: `undefined` if no error occurred
*/
export function useObjectValueOnce<Value = unknown>(query: Query | undefined | null): UseObjectValueOnceResult<Value> {
export function useObjectValueOnce<Value = unknown>(
query: Query | undefined | null,
options?: UseObjectValueOnceOptions<Value>
): UseObjectValueOnceResult<Value> {
const { converter = (snap: DataSnapshot) => snap.val() } = options ?? {};

const getData = useCallback(async (stableQuery: Query) => {
const snap = await get(stableQuery);
return snap.val();
return converter(snap);
}, []);

return useOnce(query ?? undefined, getData, isQueryEqual);
}

0 comments on commit 8cb8511

Please sign in to comment.