Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NETWORK_THEN_CACHE policy. #18

Closed
jckw opened this issue Aug 23, 2019 · 6 comments
Closed

NETWORK_THEN_CACHE policy. #18

jckw opened this issue Aug 23, 2019 · 6 comments

Comments

@jckw
Copy link

jckw commented Aug 23, 2019

This issue is to discuss how to handle cases where we would like to try to make a network request first before using the store/cache.

This is desirable where we prefer up-to-date information, but will settle for out of data information. It seems like a common use case for offline apps, making it worth at least discussing in the context of this library.

An example might be trying to fetch comments. We don't want to show the old comments if the new ones are available, but rather want to try to fetch the latest comments first, but are happy to default to showing the old ones if necessary.

@morrys
Copy link
Owner

morrys commented Aug 23, 2019

Meanwhile it is better if I specify the policies currently provided and the behavior of the library in the offline state.

This is the behavior of the library when the application status is ONLINE:

  • network_only: Don't reuse data cached in the store; always send a network request. (This is the default behavior of Relay's existing QueryRenderer.

  • store_then_network: Reuse data cached in the store; always send a network request.

  • cache_first: Reuse data cached in the store; if the whole query is cached, skip the network request (in version 1.0.0 it will be called store-or-network to adapt to the future release of relay)

Another element that has been added inside the library is the management of the TTL of the queries that allows to define how long the data inside the store must be considered good.

When the library status is OFFLINE:

it's provided the automatic management of the STORE_ONLY policy is foreseen within the logic of the QueryRenderer. This means that when the component is rendered, the network status is checked and if it is offline, no request is made on the network.
For a better integration of this functionality I have opened this issue in react-relay so as to avoid changing the properties of the component and avoiding its re-rendering

Furthermore, if the application is offline the garbage collector is disabled.

Aren't these features sufficient to cover this requirement?

@jckw
Copy link
Author

jckw commented Aug 27, 2019

Thanks very much for that explanation, it's really helpful! I think this helps me explain the problem I'm running into.

The current options do not seem sufficient for tackling this scenario:

I have a screen that loads a user profile, so requests data from a me field, e.g.

query ProfileScreenQuery {
  me {
    id
    name
  }
}

Before the user is logged in, me was in the store as null from an earlier query. For example:

query InitialFeatureFlagQuery {
  me {
    userFeaturesFlags {
      id
    }
  }
  globalFeatureFlags {
    id
  }
}

returned me as null.

So when the Profile screen is loaded, and the ProfileScreenQuery is made, this is my understanding of what happens:

  • using STORE_THEN_NETWORK, we pass me as null before we complete the query, so would need a second intermediate/loading screen before we can show the "name".
  • using CACHE_FIRST, we pass me as null before we complete the query, so would need a second intermediate/loading screen before we can show the "name".
  • using NETWORK_ONLY, we lose the benefits of this library by not using the cached data from the store.

In summary, the use-case for NETWORK_THEN_CACHE would be any case where only "complete" data is acceptable, (which we know we have if we've made that query before).

So I guess you could describe what I'm looking for as "STORE_THEN_NETWORK if we've made the query before, but NETWORK_ONLY if it this is the first time we're running this query".

@morrys
Copy link
Owner

morrys commented Aug 27, 2019

even when executing the query with NETWORK_ONLY it is necessary to loading.
In the QueryRenderer I also added the cached property to tell if the information was retrieved from the store, so you could solve using the STORE_THEN_NETWORK policy and manage with this condition cached === true && me === null the loading.

@jckw
Copy link
Author

jckw commented Aug 27, 2019

I guess that's a decent work around. However, this problem repeats itself in multiple places in the tree. Say we update ProfileScreenQuery to include a age field.

query ProfileScreenQuery {
  me {
    id
    name
    age
  }
}

Now the store will be missing "age" the first time this query is made, so we need another loading screen that shows the loading screen if cached === true && !!me.age.

There are so many variations of this problem that it would make sense to just hash the query and store it as a "has been made" (which indicates whether the cached result is usable enough).

Without a feature like this, we'd end up with lots of components looking like this: name && <div>{name}</div>. Or is there a better way to handle this?

@morrys
Copy link
Owner

morrys commented Aug 27, 2019

For this problem I recommend following this issue and the official response

@jckw
Copy link
Author

jckw commented Aug 27, 2019

I've now realised the behaviour I was looking for was the default behaviour of NETWORK_ONLY when using this library 🤦‍♂.

Thank you for the help! The missing data problem is definitely interesting and still worth thinking about for users of STORE_THEN_NETWORK.

@jckw jckw closed this as completed Aug 27, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants