Add search hooks
This commit is contained in:
parent
6f2bff218f
commit
4daec82206
3 changed files with 90 additions and 6 deletions
|
@ -31,7 +31,7 @@ type UseQueryHook<TData, TVariables> = (
|
||||||
function makeQuery<TData, TVariables>(
|
function makeQuery<TData, TVariables>(
|
||||||
query: DocumentNode
|
query: DocumentNode
|
||||||
): UseQueryHook<TData, TVariables> {
|
): UseQueryHook<TData, TVariables> {
|
||||||
function useQuery<TData, TVariables>({
|
function useQuery({
|
||||||
displayLoader,
|
displayLoader,
|
||||||
require,
|
require,
|
||||||
skip,
|
skip,
|
||||||
|
|
|
@ -1,18 +1,57 @@
|
||||||
import { DocumentNode } from "graphql";
|
import { DocumentNode } from "graphql";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
import { QueryResult } from "react-apollo";
|
||||||
|
|
||||||
import Debounce from "../components/Debounce";
|
import makeQuery, { UseQueryResult } from "./makeQuery";
|
||||||
import { UseQueryResult } from "./makeQuery";
|
import useDebounce from "./useDebounce";
|
||||||
|
|
||||||
export interface SearchQueryVariables {
|
export interface SearchVariables {
|
||||||
after?: string;
|
after?: string;
|
||||||
first: number;
|
first: number;
|
||||||
query: string;
|
query: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeSearch<TData, TVariables extends SearchQueryVariables>(
|
export interface UseSearchResult<TData, TVariables extends SearchVariables> {
|
||||||
|
loadMore: () => void;
|
||||||
|
result: QueryResult<TData, TVariables>;
|
||||||
|
search: (query: string) => void;
|
||||||
|
}
|
||||||
|
export type UseSearchOpts<TVariables extends SearchVariables> = Partial<{
|
||||||
|
skip: boolean;
|
||||||
|
variables: TVariables;
|
||||||
|
}>;
|
||||||
|
export type UseSearchHook<TData, TVariables extends SearchVariables> = (
|
||||||
|
opts: UseSearchOpts<TVariables>
|
||||||
|
) => UseSearchResult<TData, TVariables>;
|
||||||
|
|
||||||
|
function makeSearch<TData, TVariables extends SearchVariables>(
|
||||||
query: DocumentNode,
|
query: DocumentNode,
|
||||||
loadMoreFn: (result: UseQueryResult<TData, TVariables>) => void
|
loadMoreFn: (result: UseQueryResult<TData, TVariables>) => void
|
||||||
): UseSearchHook<TData, TVariables> {
|
): UseSearchHook<TData, TVariables> {
|
||||||
const [searchQuery, setSearchQuery] = useState("");
|
const useSearchQuery = makeQuery<TData, TVariables>(query);
|
||||||
|
|
||||||
|
function useSearch(
|
||||||
|
opts: UseSearchOpts<TVariables>
|
||||||
|
): UseSearchResult<TData, TVariables> {
|
||||||
|
const [searchQuery, setSearchQuery] = useState("");
|
||||||
|
const debouncedSearch = useDebounce(setSearchQuery);
|
||||||
|
const result = useSearchQuery({
|
||||||
|
...opts,
|
||||||
|
displayLoader: true,
|
||||||
|
variables: {
|
||||||
|
...opts.variables,
|
||||||
|
query: searchQuery
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
loadMore: () => loadMoreFn(result),
|
||||||
|
result,
|
||||||
|
search: debouncedSearch
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return useSearch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default makeSearch;
|
||||||
|
|
45
src/hooks/makeTopLevelSearch.ts
Normal file
45
src/hooks/makeTopLevelSearch.ts
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
import { DocumentNode } from "graphql";
|
||||||
|
|
||||||
|
import { PageInfoFragment } from "@saleor/types/PageInfoFragment";
|
||||||
|
import makeSearch, { SearchVariables, UseSearchHook } from "./makeSearch";
|
||||||
|
|
||||||
|
export interface SearchData {
|
||||||
|
search: {
|
||||||
|
edges: Array<{
|
||||||
|
node: any;
|
||||||
|
}>;
|
||||||
|
pageInfo: PageInfoFragment;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeTopLevelSearch<
|
||||||
|
TData extends SearchData,
|
||||||
|
TVariables extends SearchVariables
|
||||||
|
>(query: DocumentNode): UseSearchHook<TData, TVariables> {
|
||||||
|
return makeSearch<TData, TVariables>(query, result => {
|
||||||
|
if (result.data.search.pageInfo.hasNextPage) {
|
||||||
|
result.loadMore(
|
||||||
|
(prev, next) => {
|
||||||
|
if (
|
||||||
|
prev.search.pageInfo.endCursor === next.search.pageInfo.endCursor
|
||||||
|
) {
|
||||||
|
return prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...prev,
|
||||||
|
search: {
|
||||||
|
...prev.search,
|
||||||
|
edges: [...prev.search.edges, ...next.search.edges],
|
||||||
|
pageInfo: next.search.pageInfo
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
{
|
||||||
|
...result.variables,
|
||||||
|
after: result.data.search.pageInfo.endCursor
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
Loading…
Reference in a new issue