React-apollo: props and options get called multiple times while fetching a query

Created on 27 Apr 2017  路  25Comments  路  Source: apollographql/react-apollo

I am using react apollo version "^1.0.0" and trying to fetch a query. While debugging my code I noticed that the "options" and "props" parts called several times before the query is fetched (see comments in the code snippet). This behavior happens in other queries in my code. Is there a reason for it or did I miss something. Here is the container where I am fetching a query

export default graphql(query, {
  name: 'users',

  // this function is called several times by Apollo client per query
  props: ({ users: { loading, users, fetchMore } }) => ({........}),

  // this function is called several times by Apollo client per query
  options: (props) => ( {variables: {......}} ) 

)(Users);

Most helpful comment

Reopening since there's now a reproduction!

All 25 comments

Hi @ablbol. I'm not too familiar with that part of the codebase, but if you provide a reproduction with react-apollo-error-template, I'll look into it!

Or maybe @jbaxleyiii has an idea! :)

A reproduction would be great! If I had to hazard a guess I would say that something else is rerendering your wrapped component while the query is in flight. Options and props get called each time the component is rerendered if the props coming down the tree have changed

@helfer @jbaxleyiii

I know @ablbol closed this issue, however I'm seeing this behavior particularly with the options() method, not the props() method.

A very simple reproduction can be found here: https://github.com/newoga/react-apollo-issue-660

This is the console output from the reproduction when the application starts:

image

FYI I did a little digging myself. I added additional logging in my node_modules\react-apollo\react-apollo.browser.umd.js one line before each call of calculateOptions (which calls mapPropsToOptions) and each direct call of mapPropsToOptions.

It seems like there are a number of methods that each recalculates the options for themselves for the same props.

Below is the log output I have. It shows each react-apollo client method that is calling the user's option mapping function.

[node_modules/react-apollo] shouldSkip() -- mapPropsToOptions
App.js:49 options() called...

App.js:50 
react-apollo.browser.umd.js:286 [node_modules/react-apollo] setInitialProps -- calculateOptions
App.js:49 options() called...

App.js:50 
react-apollo.browser.umd.js:381 [node_modules/react-apollo] shouldSkip() -- mapPropsToOptions
App.js:49 options() called...

App.js:50 
react-apollo.browser.umd.js:406 [node_modules/react-apollo] dataForChild -- calculateOptions
App.js:49 options() called...

App.js:50 
App.js:6 App rendering...

react-apollo.browser.umd.js:381 [node_modules/react-apollo] shouldSkip() -- mapPropsToOptions
App.js:49 options() called...

App.js:50 
react-apollo.browser.umd.js:381 [node_modules/react-apollo] shouldSkip() -- mapPropsToOptions
App.js:49 options() called...

App.js:50 
react-apollo.browser.umd.js:406 [node_modules/react-apollo] dataForChild -- calculateOptions
App.js:49 options() called...

App.js:50 
App.js:6 App rendering...

I haven't investigate the source code enough to provide any recommendations to circumvent this, but hopefully this adds some clarity to the problem.

tl;dr react-client's graphql methods such as shouldSkip, dataForChild, and setInitialProps each are calling the user's mapping function themselves instead of sharing the result of one computation of the options for each re-render. In addition, the mapper function is called when the graphql function in constructed (not sure if this is necessary).

@helfer @jbaxleyiii I haven't had a chance to explore this any further, but do you think we should reopen this issue? If I get around to it, I can try to write some failing tests for this.

Any updates?

Reopening since there's now a reproduction!

I noticed this same problem, A component that takes a variable / id from the router params, will re-render 7-8 times each time the component loads. The id comes from react-router-4 match.params.id

On a full page refresh It reloads 8 total times - 5 times, then when the data comes back from the graphql endpoint, it runs 3 more times. The difference in the 2 objects are that loading is false, and account has data once loaded.

screen shot 2017-09-17 at 12 12 26 pm

I'm using gql/graphql from react-apollo@^1.4.15: version "1.4.15" and apollo-client@beta

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!

@jbaxleyiii can you reproduce this problem?

Any updates guys?

const HomeScreenWithData = graphql(query, {
  options: ({currentUser}) => {
    const _ownerId = currentUser ? currentUser._id : '';
    return {variables: {_ownerId}};
  },
  props: props => props,
})(HomeScreen);

Here's my simple code to fetch user data but it seems fetching 4 times then trigger rendering 4 times as well. :\

I'm seeing this behavior as well. I removed all apollo code to see if it was something router related, but that was not the problem. The one good thing I noticed was my GraphQL server wasn't getting hit multiple times, only once. It's just the options function that gets called multiple times.

Same here. Seeing it call about 7-8 times in the client (added a console.log to my function that return options for graphql()() )

@jbaxleyiii I am seeing this as well, and it's really making pagination difficult

Same here. Also I'm wondering if there is a way to abort the query, when I pass a route with an invalid ID. E.g. /people/<errorID>/new. Right now I am getting infinite retries when the ID doesn't match, which asplodes the browser.

Same thing happening here. Being called multiple times in a row..

I'm also facing the same issue.

Here's the code I've written:

Parent Component:
screen shot 2017-12-05 at 8 46 32 am

Options Call
screen shot 2017-12-05 at 8 45 26 am

Output :
screen shot 2017-12-05 at 8 44 48 am

+1. Its getting too annoying. This is increasing unnecessary load on my db. Please fix this or suggest a workaround.

Aah, my bad , i had specified the pollInterval=10000 in the config.options (passed to graphql function as 2nd parameter). Removing that everything works fine :+1:

I'm having a similar issue on page load. GraphQL query or mutation firing on page load.

login function only gets called on onClick but query is still firing prematurely and throwing console errors.

`` login(event) { event.preventDefault(); this.props.mutate({ variables: { userName: this.state.userName, password: this.state.password } }).then(({ data }) => { console.log(data); }).catch((error) => { console.log(error); }) };

export default graphql(loginQuery)(withStyles(s)(Login));

any update?

any updates I am also facing the same issue, and I also noticed that If the user clicks on some component and click on other component the previous component query is called after rendering the current component results.

To anyone that is having this problem:

It seems like this issue was fixed in v2 of react-apollo 馃帀. Many of the internals of react-apollo (and its dependencies) were refactored and/or rewritten in v2 and it appears most of the current development/activity is focused there. I rebased my original reproduction of this issue in this commit and it seems like the behavior is now gone.

If you are running v1 of react-apollo and are having this issue, I recommend updating to v2 and seeing if that fixes your issue. The migration guide to v2 is here. I've been running v2 in production for a while now and haven't had any problems.

If you are running v2 and are having this issue, I recommend cloning the latest version of the react-apollo-error-template and trying to create a reproduction there. (I was unsuccessful in doing so)

@jbaxleyiii @helfer @stubailo I briefly looked at the source code in v2 and I can't see a scenario where this behavior would still be present. If there aren't any intentions of patching v1, I think we can close this issue.

I can confirm that 2.1.3 does not have this bug
2.0.4 - https://tppr.me/WSVkx
2.1.3 - https://tppr.me/WX5sa

As mentioned in https://github.com/apollographql/react-apollo/issues/660#issuecomment-374066888, this issue has been resolved.

Was this page helpful?
0 / 5 - 0 ratings