This is a discussion issue for documenting actual use-cases and suggestions for an improved API that people have.
Started because of this issue: https://github.com/apollographql/react-apollo/pull/461
@wmertens @calebmer @stubailo @jbaxleyiii let's continue the discussion about API improvements here!
I've been thinking a lot about multiple clients and prefetching queries. These are our two largest needs for what's next. I'm hoping to have API designs soon for them. That and I REALLY want good flow support + the codegen support for flow
I think an easy way to use subscriptions from React would be high on my list.
Current use cases (excuse the slight frustration leaking through):
update: "merge"|"replace"|fn(prev) option for each query in the query (fn gets only the previous graphql result of the previous call, not the whole data thing), with "merge" the default.@graphql attached.Not using fragments or unions. Ids are globally unique.
Comments from other issues:
mutate should be the fallback name. That way it's easy to attach several at once.options is a very opaque object, and options.variables is so common that it should be separate. Also it's hard to remember which one is the function (options or variables and whether ownProps is just an argument or an attribute in an argument object.$foo is given. This can be done by automatically creating e.g. $fooNonNull if it is used in the query. That would mean not having to do fooNonNull: !!foo on every such query, just write query(foo: $foo) @include(if: $fooNonNull) and it would just work.data: ... wrapped around, but the previous queries just have the actual query data. I may be misremembering.updateQueries set up correctly so the component only had to call this.props.mutation(inputs). Instead, I would expect that sort of setup to be part of the @graphql configuration of the mutation.@graphql might take an object as its first argument that combines query and all the other options. This can be optional of course, to provide both use casesIn general, the API feels haphazard, and is not very orthogonal. It has some features that would be better done in separate libraries (skip, props), and defining queries turns ugly very quickly. @graphql(someQuery) is nice, but @graphql(someQuery, {options: (whichargs?) => ({variables: {...}})}) is decidedly not.
I really think that the concept is wonderful, and the execution can be improved to make it wonderful too. (The concept being "I need this slice of server state. I don't care how you get it.")
Some solutions:
@graphql(options) which adds a prop [options.name || options.query.name] to the component instead of data? That would already take care of a couple of pain points for me. The old @graphql(query, options) would map to @graphql({...options, query, name: options.name || 'data'}). options() attribute. You already change the apollo-client API, so why use this as the prime configuration? It would be better to provide an optimized-for-react API and then map that to apollo-client calls.Use case(s):
We check data.error in store both on client and server to:
Our GraphQL server speaks to multiple APIs and returns a GraphQL response which is handled by react-apollo. Even if there is an error, if it is not a critical failure, we wish to render a page with partial data.
Current behaviour
| Server-side | Client-side |
|-------------| -----------|
| getDataFromTree throws an error if there is _any_ error. | We can access errors through the data.error property here |
| Handle errors using try catch | Handle errors through accessing data.error. No try catch required |
Suggestion
Please let me know if you require more information or wish to change the format of the use case.
I am working on a timeline based component that fetches data from GraphQL backend. When user clicks on previous or next button, I need to call fetchMore by providing a new time range. For any given time range, there is also possible pagination involved. To keep track of whether data is fully loaded or still needs fetchMore for pagination, I have a data structure, similar to the following
dataStatus = {{'04_2017': {loaded: false, pageInfo: ...},
'03_2017': {loaded: true, pageInfo: ...}
... }
and keep it updated when fetchMore is initially called and in a callback function in updateQuery.
As in
loadMoreEvents: (newDateRange, newAfter, callback) => {
return fetchMore({
variables: {
dateRange: newDateRange,
after: newAfter
},
updateQuery: (previousResult, { fetchMoreResult, queryVariables }) => {
// Note: bug or not queryVariables always return original variables, not variables used in fetchMore.
const newNodes = fetchMoreResult.data.calendarReleases.nodes
const pageInfo = fetchMoreResult.data.calendarReleases.pageInfo
const hasMore = (newNodes.length === queryVariables.first)
callback(newDateRange, hasMore, pageInfo)
return {
calendarReleases: {
nodes: [...previousResult.calendarReleases.nodes, ...newNodes]
}
}
}
})
}
Perhaps there are better ways to solve this type of timeline related queries. Would it be feasible to have Apollo keeps track of which data set is retrieved through which variables passed to fetchMore?
This issue has been automatically labled because it has not had recent activity. If you have not received a response from anyone, please mention the repository maintainer (most likely @jbaxleyiii). It will be closed if no further activity occurs. Thank you for your contributions to React Apollo!
This issue has been automatically closed because it has not had recent activity after being marked as no recent activyt. If you belive this issue is still a problem or should be reopened, please reopen it! Thank you for your contributions to React Apollo!
Most helpful comment
Use case(s):
Consistent rendering and error handling between client and server
We check
data.errorin store both on client and server to:Our GraphQL server speaks to multiple APIs and returns a GraphQL response which is handled by
react-apollo. Even if there is an error, if it is not a critical failure, we wish to render a page with partial data.Current behaviour
| Server-side | Client-side |
|-------------| -----------|
|
getDataFromTreethrows an error if there is _any_ error. | We can access errors through thedata.errorproperty here || Handle errors using
try catch| Handle errors through accessing data.error. Notry catchrequired |Suggestion
Please let me know if you require more information or wish to change the format of the use case.