-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
Implement RelayStore.reset() #233
Comments
This will be useful for the prototyping tools (#240). Right now, it's possible to paint yourself into a corner where you have cached results for a given field/call combination, but you've changed the underlying resolve method in the schema tab. |
Great, need this :) |
Things that need to be touched just from a quick peek at the code:
The more interesting part: How should |
@clentfort Yeah, the tricky part isn't so much the resetting as it is deciding what to do if components are still mounted. |
@josephsavona: If we change some stuff we could use the infrastructure that is available for the garbage collector and simply error-out if any data is still subscribed to. |
Is there any work around for this that could be used on react-native? A page refresh isn't really an option there. :) |
@skevy The workaround for now in React Native is the brute-force equivalent of a page refresh - tear down the current JS context and start a new one. |
Here's what needs to change to make this happen:
I started a rough version of this at josephsavona@7fdb68d - feel free to use this as the basis of the above implementation. It implements the invariant check I mentioned above, but all the new methods need tests. |
Would it be reasonable for the My concern is that only exposing this low-level This could become quite complex to do, especially if data is fetched both before class App extends Component {
state = { loginState: 'SIGNED_OUT' };
handleLogin = () => {
login().then(() => {
this.setState({ loginState: 'TRANSITION' }, () => {
Relay.Store.reset();
this.setState({ loginState: 'SIGNED_IN' });
});
})
};
handleLogout = () => {
logout().then(() => {
this.setState({ loginState: 'TRANSITION' }, () => {
Relay.Store.reset();
this.setState({ loginState: 'SIGNED_OUT' });
});
})
};
render() {
switch (this.state.loginState) {
case 'SIGNED_OUT':
return (
<Relay.RootContainer
Component={Login}
renderFetched={(data) =>
<Login {...data} onLogin={this.handleLogin} />
} />
);
case 'TRANSITION':
return null;
case 'SIGNED_IN':
return (
<Relay.RootContainer
Component={Profile}
renderFetched={(data) =>
<Profile {...data} onLogout={this.handleLogout} />
} />
);
}
} If the data would be tied to the lifecycle of |
I like the idea of not having that global singleton Relay store. Ignoring implementation difficulties for now, there are a couple of practical API considerations.
|
@fson Interesting idea. For background, we've found lots of use cases for having multiple That said, you're absolutely right that a more complete solution is to integrate RelayRootContainer into the
|
@taion We agree. Earlier versions of Relay had way more global state, and we've been steadily refactoring to move this state into instance objects. The eventual goal is that you could configure a |
What about (optionally) separating that out from Then each This would work well for the standard RN use case, because you could just wrap the navigator in a The benefit of doing this would be that it might be possible to avoid an explicit imperative |
@taion Yes! That's basically the long-term vision. However, there's still a bunch of work needed to get there. The approach I outlined for |
It would also be great to have the ability to invalidate certain entries of the cache. E.g. if we know that certain data can be updated from other sources or other users it would be great to be able to say, for example, after 10min invalidate this part of the cache and if the user re-visits that page requery the invalidated parts that are needed to display the current components. |
This issue will largely be addressed by #558, which makes all Relay state contextual (implements the @Globegitter - Yeah, that would be cool. The API could be |
Instead of (or perhaps in addition to) invalidating it'd be nice to be able
|
@KyleAMathews Yup, we're looking into this. However, in early experiments storing the metadata required to record expiration times had a non-trivial impact on product performance. |
@KyleAMathews @josephsavona yep being able to set expiration times would be great as well. But yeah getting performance right is of course important as well ;) |
Could expiration exist outside of core? Seems like if we exposed I think it'd be really nice to keep the core fairly simple and break out |
Yeah I can definitely see supporting an expire command being A related question, could you invalidate on a timer while the view is
|
@KyleAMathews This is trivial to do today: use const query = Relay.createQuery(Relay.QL`query { ... }`, {var: 'foo'});
Relay.Store.forceFetch({query}, readyState => { ... }); |
@devknoll Good question. It isn't possible today without hijacking some internal methods. It could be an interesting experiment to try building it and see what hooks you need. Again though, the main consideration is perf. |
👍 I've been very happy with using |
@josephsavona hello You mention a "forceFetch" method but I don't see it documented here is it normal? https://facebook.github.io/relay/docs/api-reference-relay-store.html |
You can find it here: https://facebook.github.io/relay/docs/api-reference-relay-container.html#forcefetch |
thanks I wasn't looking at the good page! |
Is there way to make it work as Reason why I just don't call forceFetch inside component that has full query is simply because I need to do it somewhere else.
|
Kind of a related question how you guys handle after user logging in orther than full page reloading? Some views need to be added or updated |
@tuananhtd that's a great question for Stack Overflow :-) |
I don't see any reason for this to be open anymore. Based on the discussion in #898 (comment) that concluded that this feature isn't needed now when the new environment api has landed (#558). |
@edvinerikson The question of how to reset the Relay store still comes up occasionally, so having this issue is a useful way for users to find the current status. I'll update the description to make the plan more clear. |
How do you emulate reset() using the Environment API? |
This is how I'm doing it: util.js
index.ios.js
use Relay.Renderer directly or create your own wrapper than passes |
I'm closing as this is now possible in the release branch. Stores cannot be reset, instead you can create a new instance of |
At the moment, using custom environments won't work with mutations. The patch is in the repo at b44fcb2 , but it hasn't been released, so you'll have to manually patch it in order to get custom environments to work with mutations. Once you're patched, you can do If you don't use the patched version, Mutations won't find cached objects correctly given in the inputs Further reading: #1136 |
@joenoon Have you got an example app which uses this to reset the environment? ^ |
@jamesone actually what I do now is a bit different. I haven't tried changing the entire environment out in months, but I remember having problems getting it to work right in my app. Sounds like it might have been addressed since then. Not sure if this will address your needs, but what I've been doing that seems to work pretty good for me is I have a simple mutation that by default has a fatQuery that will force the entire
On the server side its just a mutation with this:
|
Why isn't there a command |
Because it's much cleaner to just instantiate a And #233 (comment) no longer applies. So just do the right thing and make a new environment. |
If it's for logout, just do |
Sorry to dig up this old issue @taion. I've been following the approach you mentioned (creating a new store) for a while now, but an issue has just come to light. The easiest thing seems to be to avoid creating a new store and instead clear the old one. Has anyone else experienced a similar issue and found a solution? Is everyone else updating their context using a hook/context when logging out? |
For logout, we recommend either reloading the application ( We do not plan on providing a |
Thanks for the response @josephsavona . I'm using this in a React Native context. It's possible to reload the app in a similar way, but it looks super amateur and it's not typically how apps behave when you logout. Agree with the new environment approach being tricky. Could this invalidateStore function work? Or would that not "reset" everything on the environment that we need? |
Note that |
The motivating use case here is clearing the cache on logout. We already have an internal task for this (t6995165) but I'm creating this issue for external visibility.
For now, the workaround is to do a full page refresh on logout. The long-term plan here is #559 - instead of resetting the store, applications will be create new instances of
RelayEnvironment
when necessary.The text was updated successfully, but these errors were encountered: