Hooks
Referência dos três hooks React exportados por @salve-software/react-native-salve-db. Para a
explicação narrativa — por que eles existem, como a re-renderização ao vivo funciona, e como o
sync interage com eles — veja Hooks. Esta página é focada em assinaturas.
import { useQuery, useInfiniteQuery, useDatabaseReady } from '@salve-software/react-native-salve-db';
useQuery
function useQuery<TSchema extends AnySchema>(
props: IUseQueryProps<TSchema>
): IUseQueryResult<InferSelectModel<TSchema>>;
interface IUseQueryProps<TSchema> {
schema: TSchema;
queryFn: (q: SelectQueryBuilder<TSchema>) => SelectQueryBuilder<TSchema>;
deps?: readonly JsonValue[];
}
interface IUseQueryResult<TRow> {
data: TRow[] | null;
error: unknown;
isLoading: boolean;
}
Executa um select contra schema, com cache e mantido ao vivo: ele re-executa e re-renderiza
automaticamente sempre que uma escrita toca a tabela de schema, não importa a origem (este hook,
outra tela, SQL bruto, ou sync em background nativo). Requer useDatabaseReady
internamente — data permanece null e isLoading permanece true até que o banco de dados
tenha terminado configure/register. Se schema.sync?.enabled for true, a montagem também
solicita um sync de leitura para aquele schema.
deps é comparado com uma stringificação estrutural estável — passe quaisquer valores
primitivos/array/objeto dos quais seu closure queryFn depende (por exemplo, um valor de filtro),
da mesma forma que você faria com um array de deps de useEffect.
const { data, isLoading, error } = useQuery({
schema: UserSchema,
queryFn: (q) => q.where(eq('active', true)).orderBy('createdAt', 'desc'),
deps: [],
});
useInfiniteQuery
function useInfiniteQuery<TSchema extends AnySchema>(
props: IUseInfiniteQueryProps<TSchema>
): IUseInfiniteQueryResult<Row<TSchema>>;
interface IUseInfiniteQueryProps<TSchema> {
schema: TSchema;
/** Aplique where()/orderBy() aqui — não chame limit()/offset(), o hook gerencia a paginação. */
queryFn: (q: SelectQueryBuilder<TSchema>) => SelectQueryBuilder<TSchema>;
/** Linhas buscadas por página, repassadas para .limit() (sujeito a MAX_SYNC_PAGE_SIZE). */
pageSize: number;
deps?: readonly JsonValue[];
}
interface IUseInfiniteQueryResult<TRow> {
/** Todas as páginas carregadas, achatadas em um único array, na ordem de busca. */
data: TRow[] | null;
error: unknown;
/** True até que a primeira página tenha carregado. */
isLoading: boolean;
hasNextPage: boolean;
/** No-op se hasNextPage for false. */
fetchNextPage: () => void;
}
Variante paginada de useQuery: carrega pageSize linhas por vez via fetchNextPage(),
acumulando páginas em data. pageSize deve ser um inteiro positivo, senão o hook lança um erro.
Mantido ao vivo da mesma forma que useQuery — qualquer escrita na tabela de schema (de
qualquer origem) reinicia para a página 0 e refaz a busca, de forma que o estado de paginação
nunca diverge do que está em disco. Não é indicado para feeds que preservam o scroll com
"inserir no topo" — uma escrita sempre reinicia a partir da página 0.
const { data, hasNextPage, fetchNextPage, isLoading } = useInfiniteQuery({
schema: UserSchema,
queryFn: (q) => q.orderBy('createdAt', 'desc'),
pageSize: 20,
});
useDatabaseReady
function useDatabaseReady(): IDatabaseReadyState;
interface IDatabaseReadyState {
isReady: boolean;
isLoading: boolean;
error: unknown;
}
Lê o estado de prontidão do banco de dados definido pelo SalveDbProvider ancestral mais próximo.
Usado para bloquear telas/queries até que configure/register tenham terminado, e para expor
uma falha no momento da inicialização sem quebrar o app. useQuery e useInfiniteQuery já chamam
isso internamente — use-o diretamente apenas para bloqueio a nível de tela, fora desses hooks.
const { isReady, isLoading, error } = useDatabaseReady();
if (!isReady) return <SplashScreen loading={isLoading} error={error} />;