Relay: Suggestion: add Optional varieties to useQuery

Created on 8 Nov 2019  路  8Comments  路  Source: facebook/relay

I'm not sure if this is 'supported/intended' behaviour, but QueryRenderer allows you to pass an undefined query prop. If no query prop is supplied, then no data is fetched.

This is useful for some components which only need to fetch data under certain circumstances.

The new experimental hooks have no way of omitting the first argument.

I suggest introducing optional varieties of the use LazyLoad / Preloaded Queries that allow the conditional fetching of data.

wontfix

Most helpful comment

@Togrias yeah there's things I don't like about it, too. I just like the "render-as-you-fetch" concept, starting the request in the callback, and passing a "resource" that represents that fetch up into state, to render when ready. And it offers a way to fetch optionally.

That said, I've never understood why optional fetching has never been an explicitly accounted-for use-case. Made me wonder how other people handle it, because it seems to come up all the time for me (eg. empty input).

All 8 comments

I've struggled with this in every version of Relay, but I think experimental Relay would have you "render-as-you-fetch" with preloadQuery/usePreloadedQuery, as demonstrated in this sandbox, where preloadQuery is setResource(fetchTranslation(value)) and usePreloadedQuery is resource.read(). Since fetching happens during state initialization and then callbacks, you can set the state to null (when you don't want a query (like when an input is empty). I appreciate this pattern a lot, but have found it introduces some issues of its own. Any insights would be much appreciated!

@dminkovsky following your example, calling usePreloadedQuery where preloadedQuery is null would throw an error.
My main issue is that hooks can't be skipped during render. So even if you know that preloadedQuery is null, you can't skip calling usePreloadedQuery().
Compare to the old <QueryRenderer/> component, where one can pass query={shouldSkip? undefined : graphql...} as a prop to "disable" it.

@Togrias as I implemented it, usePreloadedQuery() lives in its own component, and that component is conditionally rendered based on whether preloadQuery is null. The suspense boundary is then around the component that contains usePreloadedQuery(). Something like:

{preloadQuery && <Suspense><Component preloadQuery={preloadQuery} /></Suspense>}

where

const Component = ({preloadQuery}) => {
  const result = usePreloadedQuery(/*preloadQuery and other args*/)
  // ... render
}

If a query is loading and is not ready, it'll suspend. If there's nothing to load, nothing will render.

Yes, I'm using a workaround like your method too but I think it's like a step backwards since the current QueryRenderer allows optional queries. Also, conditionally rendering elements may force unwanted mounting/unmounting while switching "modes". Hence my suggestion.

How do you skip queries using QueryRenderer?

...} .../>

@Togrias yeah there's things I don't like about it, too. I just like the "render-as-you-fetch" concept, starting the request in the callback, and passing a "resource" that represents that fetch up into state, to render when ready. And it offers a way to fetch optionally.

That said, I've never understood why optional fetching has never been an explicitly accounted-for use-case. Made me wonder how other people handle it, because it seems to come up all the time for me (eg. empty input).

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

Was this page helpful?
0 / 5 - 0 ratings