diff --git a/contents/docs/react.mdx b/contents/docs/react.mdx index b430073d..3b621852 100644 --- a/contents/docs/react.mdx +++ b/contents/docs/react.mdx @@ -115,6 +115,45 @@ const [issues] = useSuspenseQuery(issueQuery, { Use the `suspendUntil` parameter to control how long to suspend for. The value `complete` suspends until authoritative results from the server are received. The `partial` value suspends until any non-empty data is received, or for a empty result that is `complete`. +## Query Identity + +You don't need to memoize queries. Build them inline, where you use them, and pass them straight to `useQuery`. + +Zero caches the queries you build with [ZQL](/docs/zql). Build the same query again and you usually get back the same `Query` object, even when it has `related()` or `whereExists()` callbacks written inline. So rebuilding a query on every render is cheap. You can also use a query as a dependency of `useEffect` or `useMemo`, or pass it as a prop to a component wrapped in `React.memo`: + +```tsx +import {useEffect} from 'react' +import {useQuery} from '@rocicorp/zero/react' +import {zql} from 'schema.ts' + +function IssueSearch({text}: {text: string}) { + // Rebuilt on every render. No useMemo needed. + const query = zql.issue + .where('title', 'ILIKE', `%${text}%`) + .orderBy('created', 'desc') + const [issues] = useQuery(query) + + // Scroll back to the top when the search changes. + useEffect(() => { + window.scrollTo(0, 0) + }, [query]) + + return issues.map(issue => ( +