Skip to content

Feature proposal : enable query to be a Promise<Query> in database/useObject and similar hooks #266

Open
@rpelissier

Description

@rpelissier

I have a use case that make the use of useObject quite painful.
It happens that the path of the Query is depending on another request to the Database.
As conditional Hooks are forbidden I have to create every time another layer of Component to do the first query before I can use the secundary Component with your hook.
It would be great if query can optionaly be a Promise<Query> so I don't need this extra layer.

Example code :

import { useEffect, useMemo, useState } from 'react';
import { snapshotToData, ValOptions } from './helpers';
import { ObjectHook, ObjectValHook, Val } from './types';
import { useIsEqualRef, useLoadingValue } from '../util';
import { DataSnapshot, off, onValue, Query } from 'firebase/database';

function isPromise(p: any): p is Promise<Query | null | undefined> {
  return typeof p === 'object' && typeof p['then'] === 'function';
}

export const useObject = (
  query?: Query | null | Promise<Query | null | undefined>
): ObjectHook => {
  const { error, loading, reset, setError, setValue, value } = useLoadingValue<
    DataSnapshot,
    Error
  >();

  const queryPromise: Promise<Query | null | undefined> = isPromise(query)
    ? query
    : Promise.resolve(query);

  const [resolved, setResolved] = useState(false);

  const ref = useIsEqualRef<Query>(undefined, reset);

  useEffect(() => {
    if (!resolved) {
      queryPromise.then((query) => {
        ref.current = query;
        setResolved(true);
      });
      return;
    }

    const effect = async () => {
      const query = ref.current;

      if (!query) {
        setValue(undefined);
        return;
      }

      onValue(query, setValue, setError);

      return () => {
        off(query, 'value', setValue);
      };
    };

    effect();
  }, [ref.current]);

  const resArray: ObjectHook = [value, loading, error];
  return useMemo(() => resArray, resArray);
};

Metadata

Metadata

Assignees

No one assigned

    Labels

    questionFurther information is requested

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions