Skip to content

Instantly share code, notes, and snippets.

@jakobvase
Last active January 21, 2023 19:34
Show Gist options
  • Save jakobvase/eb1fc269c4416d89c79d807d696a1899 to your computer and use it in GitHub Desktop.
Save jakobvase/eb1fc269c4416d89c79d807d696a1899 to your computer and use it in GitHub Desktop.
Relay search component
import graphql from "babel-plugin-relay/macro";
import { Suspense, useState } from "react";
import {
PreloadedQuery,
usePaginationFragment,
usePreloadedQuery,
useQueryLoader,
} from "react-relay";
import { SearchQuery } from "./__generated__/SearchQuery.graphql";
import { Search_Results$key } from "./__generated__/Search_Results.graphql";
export const Search = () => {
const [searchQuery, search] = useQueryLoader<SearchQuery>(
require("./__generated__/SearchQuery.graphql")
);
const [searchString, setSearchString] = useState("");
return (
<div className="flex flex-col gap-16">
<input
type="text"
value={searchString}
onChange={(e) => setSearchString(e.currentTarget.value)}
/>
<button type="button" onClick={() => search({ searchString, count: 5 })}>
Search
</button>
{searchQuery ? (
<Suspense>
<ResultsWrapper query={searchQuery} />
</Suspense>
) : (
"Waiting for you to search :)"
)}
</div>
);
};
const ResultsWrapper = ({ query }: { query: PreloadedQuery<SearchQuery> }) => {
const results = usePreloadedQuery(
graphql`
query SearchQuery($searchString: String!, $count: Int, $cursor: ID) {
...Search_Results
}
`,
query
);
return <Results queryFragment={results} />;
};
const Results = ({ queryFragment }: { queryFragment: Search_Results$key }) => {
const { data, hasNext, loadNext, isLoadingNext } = usePaginationFragment(
graphql`
fragment Search_Results on Query
@refetchable(queryName: "SearchResultsQuery") {
search(searchString: $searchString, first: $count, after: $cursor)
@connection(key: "Search_results") {
edges {
node {
id
}
}
}
}
`,
queryFragment
);
const results =
data.search?.edges
.filter((e) => e.node.id)
.map((e) => <p key={e.node.id}>{e.node.id}</p>) ?? [];
return (
<div className="flex flex-col gap-4">
{results.length > 0 ? results : "No results"}
<button
type="button"
disabled={isLoadingNext || !hasNext}
onClick={() => loadNext(10)}
>
Load more results
</button>
</div>
);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment