Closed ersinakinci closed 4 years ago
Another approach would be relayEnvironment.getStore().getSource().get('client:root:searchQuery')
, but that feels brittle. Also, I don't think that it solves the problem of re-rendering QueryRenderer
if searchQuery
or any of its descendants changes.
Related to https://github.com/relay-tools/found-relay/issues/297 – we don't currently support async prepareVariables
, in the same way that we don't support async getQuery
.
We could do it, but I don't really know of a good way to automatically "subscribe" to variables in the route. We don't really have a great concept of route "effects" that would let you do this in a way that's coupled to the route, rather than to the page component, though – but if I were to approach this, I'd subscribe to the relevant store entry in the component, and call router.replace(...)
whenever things updated.
Thanks for the suggestion, @taion.
I realized that because I'm using the pagination container, for my particular use case it makes more sense to rely on refetchConnection
rather than trying to reload data at the router level. It's a three step process:
... on Query
workaround to get Relay compiler to be happy):<Route
...
Component={MyComponent}
prepareVariables={(_params, { context: { environment } }) => {
const request = getRequest(graphql`
query routes_searchQuery_Query {
... on Query {
__typename
}
searchQuery {
query
selectedFacets {
id
type
}
}
}
`);
const operation = createOperationDescriptor(request);
const {
searchQuery: { query, selectedFacets },
} = environment.lookup(operation.fragment, operation).data;
return {
query,
selectedSelectors: selectedFacets,
};
}}
/>
MyComponent
, the query includes the searchQuery
field. Including this field subscribes MyComponent
to any future changes and adds the field to the results included from the query:const MyComponent = createPaginationContainer(
MyComponentInner,
{
search: graphql`
fragment MyComponent_search on Query {
searchQuery {
query
selectedFacets {
id
}
}
...
}
`
}
)
MyComponentInner
, I refetch the connection any time that searchQuery.query
or searchQuery.selectedFacets
changes:const MyComponentInner = ({ relay, search: { query, selectedFacets } }) => {
// Update search results when the query or filters change
useEffect(
() => {
relay.refetchConnection(20, null, {
query,
facets: selectedFacets,
});
},
[query, relay, selectedFacets]
);
}
One could do something similar using a refetch container, as well, when dealing with non-connection queries.
That ... on Query
workaround was my workaround https://graphql.slack.com/archives/G95JXAN64/p1588702284062200 :p
But, yeah, if you're using a container that can refetch, your approach there looks good.
Ahaha. props
where props
are due.
Thanks for the feedback :-)
I'm trying to provide variables inside my
prepareVariables
function from Relay's store, but I'm not sure how to do this. Here was my first shot:(I'm hydrating my Relay store beforehand so that my
searchQuery { selectedFacets }
query returns something.)This almost works. The main problem is that, for whatever reason, returning a promise causes
prepareVariables
to return nothing during SSR. I don't have any problems on my browser (SSR is running on Node 10, so async/await is supported.)Another problem is that using
fetchQuery
on a local schema causes Relay compiler to fail. This workaround works, but it causes an annoying error. @sibelius suggested a different workaround using hooks, but that doesn't apply here sinceprepareVariables
isn't a React component.Lastly, I'm not sure of how to make the
QueryRenderer
re-render when there's a change to the variables that I'm getting from the store viaprepareVariables
. I want it such that it will re-run the query if the results ofsearchQuery { selectedFacets }
changes in any way; or even better, if I could specify a comparison function to control exactly when it re-renders.Has anyone else dealt with this use case? Any suggestions would be greatly appreciated!