morrys / react-relay-offline

TypeScript library files for Relay Modern Offline
https://morrys.github.io/react-relay-offline/docs/react-relay-offline.html
MIT License
227 stars 15 forks source link

Prevent persisting of errors from queries #72

Closed matt-dalton closed 3 years ago

matt-dalton commented 3 years ago

There might already be some smart solution to this in the library, but I've not been able to find anything on it yet.

We use React Native and persist state to Async Storage. Unfortunately, we're still on an older version of react-relay-offline (1.1.0) so not sure if this question has been resolved later on.

The problem flow is:

To me it would make sense to either:

  1. Not store query results if there was an error
  2. Clear the Async Storage if there was an app crash

Are there any nice solutions to this built into the library? Or is this something we should implement?

morrys commented 3 years ago

Hi @matt-dalton, maybe you might find the mergeState function useful: https://morrys.github.io/wora/docs/cache-persist#there-is-data-in-the-storage-that-is-not-compatible-with-the-new-version-of-the-application-how-can-i-migrate-it

matt-dalton commented 3 years ago

Hmm interesting...are you suggesting using this in some middleware when returning an error request? How would I "override" the logic in react-relay-offline that currently persists the state?

morrys commented 3 years ago

This feature is useful when starting the application to verify / migrate persistent data.

Another possibility is to use the mutateKeys / mutateValues functions to modify the behavior when reading / writing keys / values from the store https://morrys.github.io/wora/docs/cache-persist#cache-options

matt-dalton commented 3 years ago

Thanks for the pointers - really helpful. I can see how mutateValues in particular would help. The thing I'm struggling with is how to establish in that function whether the entry came from a response with an error.

As well as react-relay-offline, we use a few pieces of middleware from react-relay-network-modern. I've noticed their cacheMiddleware (which we don't use) has some similar logic to what we need, where they avoid adding to the QueryResponseCache cache if there's an error. Is there a way of "blocking" the react-relay-offline persistence logic in some custom middleware somehow?

morrys commented 3 years ago

react-relay-offline works differently from cacheMiddleware in fact it uses the relay store to manage the offline and in your case it is relay that modifies the store and react-relay-offline does not modify its behavior.

If you cannot manage this exception in the network layer, you could consider clearing the store when starting the application. https://github.com/morrys/wora/blob/relay-offline%402.1.0/packages/relay-offline/src/RelayModernEnvironment.ts#L81

matt-dalton commented 3 years ago

react-relay-offline works differently from cacheMiddleware in fact it uses the relay store to manage the offline and in your case it is relay that modifies the store and react-relay-offline does not modify its behavior.

Yeah exactly - I wasn't suggesting using it. Was just saying this is an example of what we're looking for.

If you cannot manage this exception in the network layer, you could consider clearing the store when starting the application. https://github.com/morrys/wora/blob/relay-offline%402.1.0/packages/relay-offline/src/RelayModernEnvironment.ts#L81

Hmm...our application performance is very dependent on booting from a persisted store. I guess we could persist when an error on a query has been received, and then clear the store on the next app load. But this might happen reasonably often, so would be a shame to lose the performance benefit for everything. Do you think it looks like avoiding storing an errored query might NOT be possible?

morrys commented 3 years ago

maybe this thread can help you https://github.com/facebook/relay/issues/1913

matt-dalton commented 3 years ago

That's an interesting thread, and does touch on some of the underlying issues we sometimes have.

We could implement some of the suggestions there (custom error schemas, making most fields nullable), which would help. However, if there was an error, we'd still have a problem, as this would be persisted. Unless I'm missing something?

morrys commented 3 years ago

What I mean is to manage a logic of this type on the client side at the network level:

fetch(
    '/api/graphql',
    {
      method: 'POST',
      body: JSON.stringify({
        query: operation.text,
        variables,
      }),
    },
  ).then(response => response.json()).then(responeJson => {
    if (responeJson.errors) {
    throw new Error(...)
    }
    console.log(responeJson)
    return responeJson
  });
}  
matt-dalton commented 3 years ago

Ahhh so if an error is thrown in the network layer, react-relay-offline will avoid updating the store? That's the simple (and probably obvious) thing I was missing