Skip to content

Commit

Permalink
feat: adds React Suspense support to useSearchProfiles hook
Browse files Browse the repository at this point in the history
  • Loading branch information
cesarenaldi committed May 16, 2024
1 parent 3ffa198 commit 53071ca
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 24 deletions.
7 changes: 7 additions & 0 deletions .changeset/dull-walls-smoke.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@lens-protocol/react": minor
"@lens-protocol/react-native": minor
"@lens-protocol/react-web": minor
---

**feat:** adds React Suspense support to `useSearchProfiles` hook
21 changes: 11 additions & 10 deletions examples/web/src/discovery/UseSearchProfiles.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { useSearchProfiles } from '@lens-protocol/react-web';
import { ChangeEvent, useState } from 'react';
import { ChangeEvent, Suspense, startTransition, useState } from 'react';

import { ErrorMessage } from '../components/error/ErrorMessage';
import { Loading } from '../components/loading/Loading';
import { useInfiniteScroll } from '../hooks/useInfiniteScroll';
import { ProfileCard } from '../profiles/components/ProfileCard';
Expand All @@ -11,17 +10,14 @@ type SearchResultsProps = {
};

function SearchResults({ query }: SearchResultsProps) {
const { data, error, loading, hasMore, observeRef } = useInfiniteScroll(
useSearchProfiles({ query }),
const { data, hasMore, observeRef } = useInfiniteScroll(
useSearchProfiles({ query, suspense: true }),
);

if (loading) return <Loading />;

if (error) return <ErrorMessage error={error} />;

if (data.length === 0) {
return <p>No profiles found</p>;
}

return (
<div>
{data.map((profile) => (
Expand All @@ -37,7 +33,9 @@ export function UseSearchProfiles() {
const [selectedQuery, setSelectedQuery] = useState<string>();

const handleSubmit = () => {
setSelectedQuery(inputValue);
startTransition(() => {
setSelectedQuery(inputValue);
});
};

const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
Expand All @@ -53,7 +51,10 @@ export function UseSearchProfiles() {
<input onChange={handleChange} />
<button onClick={handleSubmit}>Search</button>
</div>
{selectedQuery && <SearchResults query={selectedQuery} />}

<Suspense fallback={<Loading />}>
{selectedQuery && <SearchResults query={selectedQuery} />}
</Suspense>
</div>
);
}
88 changes: 74 additions & 14 deletions packages/react/src/discovery/useSearchProfiles.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,37 @@
import {
Profile,
ProfileSearchRequest,
useSearchProfiles as useBaseSearchProfiles,
ProfileSearchWhere,
SearchProfilesDocument,
} from '@lens-protocol/api-bindings';

import { useLensApolloClient } from '../helpers/arguments';
import { PaginatedArgs, PaginatedReadResult, usePaginatedReadResult } from '../helpers/reads';
import { PaginatedArgs, PaginatedReadResult } from '../helpers/reads';
import {
SuspendablePaginatedResult,
SuspenseEnabled,
SuspensePaginatedResult,
useSuspendablePaginatedQuery,
} from '../helpers/suspense';
import { useFragmentVariables } from '../helpers/variables';

/**
* {@link useSearchProfiles} hook arguments
*/
export type UseSearchProfilesArgs = PaginatedArgs<ProfileSearchRequest>;

export type { ProfileSearchRequest, ProfileSearchWhere };

/**
* `useSearchProfiles` is a paginated hook that lets you search for profiles based on a defined criteria
* {@link useSearchProfiles} hook arguments with Suspense support
*
* @category Discovery
* @group Hooks
* @experimental This API can change without notice
*/
export type UseSuspenseSearchProfilesArgs = SuspenseEnabled<UseSearchProfilesArgs>;

/**
* `useSearchProfiles` is a paginated hook that lets you search for profiles based on a defined criteria
*
* @example
* ```tsx
* function SearchProfiles() {
* const { data, error, loading } = useSearchProfiles({ query: 'foo' });
Expand All @@ -34,13 +49,58 @@ export type UseSearchProfilesArgs = PaginatedArgs<ProfileSearchRequest>;
* );
* }
* ```
*
* @category Discovery
* @group Hooks
*/
export function useSearchProfiles(args: UseSearchProfilesArgs): PaginatedReadResult<Profile[]> {
return usePaginatedReadResult(
useBaseSearchProfiles(
useLensApolloClient({
variables: useFragmentVariables(args),
}),
),
);
export function useSearchProfiles(args: UseSearchProfilesArgs): PaginatedReadResult<Profile[]>;

/**
* `useSearchProfiles` is a paginated hook that lets you search for profiles based on a defined criteria
*
* This signature supports [React Suspense](https://react.dev/reference/react/Suspense).
*
* ```tsx
* const { data } = useSearchProfiles({
* query: 'foo',
* suspense: true,
* });
*
* console.log(data);
* ```
*
* Use [startTransition](https://react.dev/reference/react/startTransition) to avoid to re-suspend the component.
*
* ```tsx
* const [query, setQuery] = useState('bob');
*
* const { data } = useSearchProfiles({
* query,
* suspense: true,
* });
*
* const search = startTransition(() => {
* setQuery('foo');
* });
* ```
*
* @experimental This API can change without notice
* @category Discovery
* @group Hooks
*/
export function useSearchProfiles(
args: UseSuspenseSearchProfilesArgs,
): SuspensePaginatedResult<Profile[]>;

export function useSearchProfiles({
suspense = false,
...args
}: UseSearchProfilesArgs & { suspense?: boolean }): SuspendablePaginatedResult<Profile[]> {
return useSuspendablePaginatedQuery({
suspense,
query: SearchProfilesDocument,
options: useLensApolloClient({
variables: useFragmentVariables(args),
}),
});
}

0 comments on commit 53071ca

Please sign in to comment.