I wasn't quite sure if this belongs here or apollo-client as it somewhat relates to https://github.com/apollographql/apollo-client/issues/1523, however my fetchMoreResult returns the expected results. The issue is that the new result isn't passed into my component if I'm using Union types.
Intended outcome:
I'm attempting to use fetchMore with limit/offset. My query contains union types. I'd expect that after I concat fetchMoreResult with my previous result it would be passed into my component.
Actual outcome:
The new result isn't passed into the component. I have an author prop which indicates the author of the post. It can be an individual user or a company (each entity has unique properties). If I remove the author prop from my GetPosts query, everything works as expected with the newResult being passed into my component. This leads me to believe that the union type is the culprit.
How to reproduce the issue:
import React from 'react';
import { View, Text } from 'react-native';
import { graphql } from 'react-apollo';
import gql from 'graphql-tag';
const GetPosts = gql`query GetPosts($limit: Int, $offset: Int) {
posts(limit: $limit, offset: $offset) {
_id
message
createdAt
scheduledAt
authorType
author {
... on User {
_id
avatarUrl
profile {
firstName
lastName
}
}
... on Company {
_id
name
logo80
}
}
}
}
`;
class TestComponent extends React.Component {
render() {
// I would expect this to log the new props after press "loadMore"
console.log(this.props)
return (
<View style={{marginTop: 40}}>
<Text onPress={this.props.loadMore}>Push me</Text>
</View>
)
}
}
export default graphql(GetPosts, {
options: () => ({
variables: {
offset: 0,
limit: 1
}
}),
props: ({ ownProps, data }) => {
return {
...ownProps,
posts: data.posts,
loadMore: () => {
return data.fetchMore({
variables: {
offset: 1,
limit: 1
},
updateQuery: (previousResult, { fetchMoreResult }) => {
if (!fetchMoreResult) {
return previousResult;
}
const newResult = Object.assign({}, previousResult, {
posts: [...previousResult.posts, ...fetchMoreResult.posts]
});
// This logs exactly what I expect it to log, but it isn't re-rendered into the component.
console.log(newResult);
return newResult;
},
})
}
};
}
})(TestComponent);
Thanks @rpylipow! Could you provide a reproduction using the error template? That way we could step through the code and find out where the bug happens.
Please take a look at https://github.com/rpylipow/react-apollo-error-template/tree/bug/union
I have two queries: One using union types and one not using union types.
If you use the union types query then press the "load more" button (which calls fetchMore), the result of fetchMoreResult is correct, but it doesn't re-render into the component. If you use the non-union type query, everything re-renders correctly.
Passing trough the same thing:
const SearchQuery = gql`
query Search($query: String!, $endCursor: String) {
search(query: $query, first: 3, after: $endCursor) {
pageInfo {
hasNextPage
endCursor
}
edges {
node {
... on EventResult {
id
name
url
startDate
endDate
countryCode
cityName
locationName
}
... on CityResult {
id
name
url
countryCode
}
... on LocationResult {
id
name
url
cityName
countryCode
}
... on ArtistResult {
id
name
url
avatar
}
}
}
}
}
`
const SearchContainerWithData = graphql(SearchQuery, {
props: ({data: {search, loading, fetchMore, refetch}}) => {
// This is not triggered
console.log('This is not logged when fetchMore');
const results = search && search.edges.map(({node}) => node)
const hasNextPage = search && search.pageInfo.hasNextPage
const endCursor = search && search.pageInfo.endCursor
return {
results, hasNextPage, loading, endCursor,
searchFor: refetch,
loadMore: (variables) => {
return fetchMore({
variables,
updateQuery: (previousResult, {fetchMoreResult}) => {
debugger
const newEdges = fetchMoreResult.search.edges
const pageInfo = fetchMoreResult.search.pageInfo
// return here is exactly what I expect
return {
search: {
edges: [...previousResult.search.edges, ...newEdges],
pageInfo,
},
}
}
})
}
}
},
options: ({query}) => {
return {
variables: {
query
}
}
}
})(SearchContainer)
I receive the results that I expect, fetchMore method return what I'm expecting but apollo-client doesn't
The fetch more returns exactly what I expect, the apollo client redux store is updated with the data from fetchMore, but the rerender is not triggered.
same here, but everything works fine with apollo-client 0.9.0 and below
I think this is the same underlying issue as https://github.com/apollographql/apollo-client/issues/1555, using the fragment matcher there should solve the problem.
However, since this seems to have worked before, I'll have to go back and check if I inadvertently removed the old fragment matcher somewhere.
Here is another reproduction: https://github.com/yury-dymov/react-apollo-error-template
I figured out that for 0.9.0 everything works fine: https://github.com/yury-dymov/react-apollo-error-template/tree/0.9.0
@yury-dymov can you check if the solution from #1555 solves your issue in the most recent version?
with [email protected] the problem is resolved using the solution from #1555.
It is noted the using [email protected] the problem is NOT resolved
@helfer I don't think using the fragment matcher should the definitive solution.
This should be transparent to the user in my opinion. :/
looks like this was solved by #1555 on AC?
Most helpful comment
@helfer I don't think using the fragment matcher should the definitive solution.
This should be transparent to the user in my opinion. :/