-
Notifications
You must be signed in to change notification settings - Fork 117
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
apollo-cache-persist missing example with support for reactive variables #361
Comments
Im also trying to accomplis this, but Typescript maybe is giving us a clue because:
on client initialization PS: Im using @apollo/client @ 3.2.0 |
Thats a separate issue, but you can fix it with:
|
Well, thats not really a fix because you are basically |
Could be. Good point! But there's no support for reactive variables at all in this library. |
@ivnnv please check sample application. It works with typescript. |
@fullhdpixel Reactive variables will not work with persistence. That is true. PR's welcome although this is not problem with library. It is more how apollo client works. |
@wtrocki thanks for the heads up, I assumed (and I think @fullhdpixel too) this could be used to make reactiveVars to persist, because it would be a game changer to make apollo the definitive state manager solution for every case. A temporary solution could be to create a wrapper in between the setter getter of the reactive vars and localStorage? |
Here is a temporary fix outside of apollo-cache-persist Lets say you have a reactiveVar mutation like so, you can do the localStorage.setItem in this mutation operation.
In your component you retrieve the information from the localStorage in a React.useEffect
|
First of all we need to determine how reactive vars are implemented. Are they stored in the InMemoryCache. Best start for me will be to add reactive var to example react web in this repo. Once that is done we can see if there is API that we can hook into. If there is that will be very quick fix. There is also performance consideration for reactive vars persistence etc.but I will skip that for the moment. CC @benjamn |
Added minimal example of using a a reactive var to store the selected values for the currencies list! |
Superb work :) |
Am I missing something? The example does not appear to work. How does it persist? |
I ran the example app and while it uses reactiveVars, it does not seem to persist. I am thus assuming that this is still an issue and the example app was just to demo this issue? Any news on fixing this? I see the apollo dev tools also can't "see" the reactive vars, so I imagine there needs to be an API to expose them to other packages? |
@pillowsoft I tried quickly get into where vars are created - they are separate from cache it seems but could not pinpoint it. For me it looks like reactive vars persistence will require figuring out apollo-client internals, |
@rebz @pillowsoft the example indeed "doesn't work" in terms of persistence. |
Relevant recent PR from @PedroBern: apollographql/apollo-client#7148 |
Reactive variables persistence isn't an Apollo/apollo-cache-persist issue, it's just a regular js issue. Here is the most barebones example of how to do it, very similar to my PR mentioned by @benjamn, that tries to simplify this process. // global scope
export const myVar = makeVar<T>(value)
// inside my root component (did mount hook for example)
// render a loading indicator while it's not ready
const previousValue = await restoreAsync(key)
myVar(previousValue)
setReady(true)
// every time I want to update the value
const update = (value:T) => {
myVar(value)
saveToTheStorageAsync(key, value)
} |
@PedroBern thats fantastic news! Thank you very much for the apollo-client PR, ill be one of the first testers once that is merged for sure |
@ivnnv nice to hear that! You don't need to wait, just copy the source code from the PR and import the reactive variables from there, it's just one file! ;) |
Is this available? I'm migrating everything from Redux so would like to use reactive variables, but everything is lost on page refresh... |
There is currently no support for persisting/restoring reactive variables in apollo-cache-persist library. When I was looking into it, I didn't find a way to attach to apollo client/cache in a way that would magically save/restore all reactive variables. (that of course doesn't mean there isn't a way, I just didn't find it). |
@wodCZ I appreciate you taking the time to check. Yeah, this is mildly frustrating. I'll remain with Apollo for the caching and the persistence will remain with Redux (massively overkill for what I'm building but it's already setup and can be swapped out in the future). Can use reactive variables for other things which is good. I will keep an eye on this for the future. It would certainly become a game changer when ready! |
There is immerse complexity and performance toll of building this support generic way. Some elements of our code can be reused but this would be most likely separate codebase/setup. I think it would be easy to hack this in your app with separate storage as for support in cache persist it will require some investigation etc. |
Hi, Inspired by other answers here's my solution to the problem, implemented in Typescript, and using
Using it is as simple as:
The value will try to initialise from localStorage, and fall back on the default. Updating will automatically update local storage too. |
@timothyarmes Why use |
No reason really. I happen to be using lodash, and the other code example that I based this version on did the same thing (but they didn't use the onNextChange mechanism) |
For me, the whole point of using the Reactive Variables was avoiding storing any auth-related info (i.e. tokens) in the local storage.
Is this solution secure in terms of storing tokens in the local storage? |
Sure, it's best not to store auth tokens, and to store refresh tokens as HTTP only cookies. However that's really nothing to do with this post which is really about persisting reactive variables for whatever reason you might have. I'll change the local storage key in my example to avoir any confusion. |
I have improved the retention of the reactive variable in the example aboveimport { makeVar, ReactiveVar } from "@apollo/client";
import { isString } from "lodash";
import AsyncStorage from "@react-native-async-storage/async-storage";
const getCleanValueForStorage = (value: unknown) => {
return isString(value) ? value : JSON.stringify(value);
};
export const getVarPersisted = async <T>(
rv: ReactiveVar<T>,
storageName: string
) => {
let value;
// Try to fetch the value from local storage
const previousValue = await AsyncStorage.getItem(storageName);
if (previousValue !== null) {
try {
const parsed = await JSON.parse(previousValue);
value = parsed;
} catch {
value = previousValue as unknown as T;
}
}
value && rv(value);
const onNextChange = (newValue: T | undefined) => {
try {
if (newValue === undefined) {
AsyncStorage.removeItem(storageName);
} else {
AsyncStorage.setItem(storageName, getCleanValueForStorage(newValue));
}
} catch (err) {
console.log("🚀 - err", err);
}
rv.onNextChange(onNextChange);
};
rv.onNextChange(onNextChange);
};
export const countVar = makeVar(0); |
'Cmon someone makes this a PR! 🏆 Can't count how many hours I lost trying to figure out a lib named cache-persist wasn't persisting the basic apollo local state example |
I want to automatically persist reactive variable value so the data will still be there after refreshing the page.
Given a reactive variable
How can I make the reactive variable persist?
The text was updated successfully, but these errors were encountered: