Skip to content
This repository has been archived by the owner on Apr 13, 2023. It is now read-only.

Slow navigation on React Native. Is there a way to delay the queries attached to a component from fetching right away? #418

Closed
booboothefool opened this issue Jan 14, 2017 · 8 comments

Comments

@booboothefool
Copy link

booboothefool commented Jan 14, 2017

aksonov/react-native-router-flux#1536

https://facebook.github.io/react-native/docs/performance.html#slow-navigator-transitions

https://github.com/brentvatne/run-after-interactions-exp/blob/master/main.js#L30

I would like to see if delaying queries until after the navigation transition solves the issue.

@booboothefool booboothefool changed the title Slow navigation on React Native. Is there a way to delay the queries attached to a component? Slow navigation on React Native. Is there a way to delay the queries attached to a component from fetching right away? Jan 14, 2017
@jbaxleyiii
Copy link
Contributor

@booboothefool you can try to skip initially, then call on componentDidMount? http://dev.apollodata.com/react/queries.html#graphql-skip

@booboothefool
Copy link
Author

booboothefool commented Jan 14, 2017

@jbaxleyiii I will give that a shot.

At the moment, I'm only familiar with the HOC wrapper way, then accessing my data via props.

When you say "call", do you mean client.query(...)? After that, how do I actually get access to that data in my component render()? Before I would just do this.props.data.myStuff.

@stubailo
Copy link
Contributor

You might also be able to use something like a noFetch + refetch.

Also, do you have any data about what is causing the slow component render, or a reproduction? IMO the first step is to confirm that it is the query fetching and not something else, since it would be surprising if intializing a query fetch takes long enough to block a render and if that's the case we should fix it.

@booboothefool
Copy link
Author

The issue was mostly react-native-router-flux. Switched to ex-navigation and app is now super smooth.

@booboothefool
Copy link
Author

booboothefool commented Jan 19, 2017

@stubailo Okay, so I don't think it's the navigation library anymore.

While I was refactoring my app to use the new navigation, it started off super smooth because I was just doing routing without any GraphQL.

I noticed the app began slowing to a crawl again when I added my giant fragments back. Specifically, I have this set of fragments I am using for a huge user profile upon entry. I attach these fragments to the drawer of my app because well, that's the entry point upon a successful login, and reuse them throughout my application.

As soon as I made this commit, I went from no delay super smooth navigation, to 2-4 seconds again. If I check out the commit before the fragments, it's amazingly fast.

Is there something I should be aware of in terms of performance when using fragments?

I'm going to do a little more and see it's the fragments or the giant query.

@booboothefool
Copy link
Author

booboothefool commented Jan 20, 2017

@stubailo Don't think it has to do with fragments. It's more the giant query.

const MY_PROFILE_QUERY = gql`
  query MyProfile {
    me {
      user_id
      username
      picture
      _geoloc {
        ...ProfileGeoloc
      }
      user_metadata {
        ...ProfileUserMetadata
      }
      identities {
        ...ProfileInstagramIdentity
      }
    }
    userPersona {
      ...ProfileUserPersona
    }
    userPhotos {
      ...ProfileUserPhotos
    }
    userShows {
      ...ProfileUserShows
    }
    userGames {
      ...ProfileUserGames
    }
    userConventions {
      ...ProfileUserConventions
    }
    userInterests
    userFavorites {
      unseenCount
      yourFavorites {
        ...ProfileHit
      }
      favoritedYou {
        ...ProfileHit
      }
      mutualFavorites {
        ...ProfileHit
      }
    }
    userVisitors {
      unseenCount
      youVisited {
        ...ProfileHit
        visited_at
      }
      visitedYou {
        ...ProfileHit
        visited_at
      }
    }
  }
  ${Profile.fragments._geoloc}
  ${Profile.fragments.user_metadata}
  ${Profile.fragments.userPhotos}
  ${Profile.fragments.userPersona}
  ${Profile.fragments.userShows}
  ${Profile.fragments.userGames}
  ${Profile.fragments.userConventions}
  ${Profile.fragments.instagram}
  ${Profile.fragments.hit}
`;

^ The reason I was doing this in the first place was as a prefetch, so if the user ever clicks "Manage Profile" or "Visitors" or a bunch of other things, they never get a spinner. On an iPhone 7, this experience is kind of a dream. It's seamless and fast, no spinners. On older phones though, when this query is done on app start, it slows everything down to the point where navigation starts taking 2-4 seconds. This isn't just the current scene, but the entire app!

I guess I can't make assumptions like this, and should only be fetching what is needed at the time, and have to show a few spinners because when I reduce the query to something like this:

(just getting rid of userVisitors and userFavorites, probably because ...ProfileHit is huge. ...ProfileHit is basically an entire profile, so it fetches the entire profile for each of the current user's visitors and favorites)

const MY_PROFILE_QUERY = gql`
  query MyProfile {
    me {
      user_id
      username
      picture
      _geoloc {
        ...ProfileGeoloc
      }
      user_metadata {
        ...ProfileUserMetadata
      }
      identities {
        ...ProfileInstagramIdentity
      }
    }
    userPersona {
      ...ProfileUserPersona
    }
    userPhotos {
      ...ProfileUserPhotos
    }
    userShows {
      ...ProfileUserShows
    }
    userGames {
      ...ProfileUserGames
    }
    userConventions {
      ...ProfileUserConventions
    }
    userInterests
  }
  ${Profile.fragments._geoloc}
  ${Profile.fragments.user_metadata}
  ${Profile.fragments.userPhotos}
  ${Profile.fragments.userPersona}
  ${Profile.fragments.userShows}
  ${Profile.fragments.userGames}
  ${Profile.fragments.userConventions}
  ${Profile.fragments.instagram}
`;

The app remains fast. So this definitely happens when there is "too much data" but I have no idea if the bottleneck is Apollo or React Native or the navigation libraries or Redux or what. I can completely work around this issue by not prematurely fetching data I don't need at the moment and adding more spinners, so I'm happy, but pretty clueless as to why "bigger query & more data" seems to slow down my app.

@Poincare
Copy link

It is unlikely that the amount of data in the store affects the cache read times - we have a benchmark for this in an outstanding PR and the cache read times are roughly constant with respect to the number of items in the cache.

@booboothefool
Copy link
Author

I think my issue has more to do with unnecessary re-renders.

Fetching more data = bigger lists = more costly re-renders of entire lists and their children.

Some React Native optimizations e.g. shouldComponentUpdate helped a lot.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants