GithubHelp home page GithubHelp logo

apollographql / apollo-cache-persist Goto Github PK

View Code? Open in Web Editor NEW
1.4K 40.0 117.0 2.13 MB

๐ŸŽ Simple persistence for all Apollo Cache implementations

License: MIT License

TypeScript 98.70% JavaScript 1.30%
offline react-native apollo graphql

apollo-cache-persist's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

apollo-cache-persist's Issues

Add peerDependency for localForage

Hi! I am using apollo-cache-persist with TypeScript and localForage.

apollo-client-persist with TypeScript seems to be incompatible with localForage version 1.60 and on because localForage changed its signature of the setItem method in version 1.6.0

The setItem method signature looks as follows in apollo-client-persist:

setItem: (key: string, data: T) => Promise<void> | void;

In localForage pre 1.6.0, the setItem method used to look like this:

setItem<T>(key: string, value: T, callback: (err: any, value: T) => void): void;

So, obviously, they were compatible. However, in localForage post 1.6.0, the setItem method now looks like this:

setItem<T>(key: string, value: T, callback?: (err: any, value: T) => void): Promise<T>;

Which, is incompatible because apollo-client-persist expects the setItem method to return either Promise<void> OR void, yet since version 1.6.0 localForage now returns Promise<T>

We as users of apollo-client-persist could be easily warned about this through the"peerDependencies" field within the apollo-client-persist package.json. Or, maybe apollo-client-persist could be upgraded to also accept Promise<T>?

On a side note, I realize this is only a problem if using TypeScript, like I am, since this would be no problem at all with JavaScript. This is actually the first time I ever find a benefit of using JavaScript over TypeScript.

ApolloClient client.clearStore() causing localStorage to be === '{}'

In my logout route I'm using the new client.clearStore() instead of resetStore().

I'm also using window.localStorage as apollo-cache-persist storage.

When I call clearStore() it set localStorage['my-storage-key'] to: {}.

This is a problem for many things, for example for the apollo-link-state defaults resolvers.

In this case is it better to delete or set to empty value the localStorage storage?

Throws error on IOS6 - 11.4 simulator with basic initialization on React-Native

screen shot 2018-09-10 at 15 33 39

Error occurs with this code

const cache = new InMemoryCache({
  dataIdFromObject: (object: any) => object.id || null,
})

persistCache({
  cache,
  storage: AsyncStorage,
})

const client = new ApolloClient({
  link: new HttpLink({
    uri: config.graphql,
  }),
  cache,
})

const StartApp = withApollo(Router)

class App extends Component<any> {
  public render() {
    return (
      <ApolloProvider client={client}>
        <StartApp />
      </ApolloProvider>
    )
  }
}

export default App

Dependencies

    "apollo-cache-inmemory": "^1.2.9",
    "apollo-cache-persist": "^0.1.1",
    "apollo-client": "^2.4.1",
    "apollo-link": "^1.2.2",
    "apollo-link-context": "^1.0.8",
    "apollo-link-http": "^1.5.4",
    "apollo-utilities": "^1.0.20",
    "graphql": "^0.14.2",
    "graphql-tag": "^2.9.2",
    "react": "16.3.1",
    "react-apollo": "^2.1.11",
    "react-native": "^0.55.4",

Current findings

With Android everything works as expected.

With iOS commenting out persistCache() -function everything works as expected.

[DOCS] Docs should state that persistCache should be awaited

Hey,

It is not clear in the documentation that persistCache is async and should be awaited.

await persistCache({
  storage: window.localStorage,
  cache,
});

Removing await breaks persistence, because the first queries will resolve before the cache is persisted, and won't resolve again when it is.

Could you please confirm that this is by design (or maybe something else is causing this and I'm wrong), and tell me if I should open a PR to clarify this in the docs?

Thanks!

Chrome Extension support

It would be useful to be able to use chrome extension persistence with this library. I would think this should be pretty easy because the API of chrome.storage is the same as window.localStorage. Is that something that could be supported?

Restoring the cache on initial render.

Hi there, I'm unsure if this is due to something relating to apollo-link-state or apollo-cache-persist, but any guidance on how I can solve this issue would be greatly appreciated as I haven't found any sample apps using apollo-cache-persist and I'm really confused on how to move forward.

here's some of my code:

https://gist.github.com/lifeiscontent/b72b8777c9707093cdd9a08b79de2fa1

the currentUser resolver is using the default resolver and the token is undefined everytime I refresh.

Question regarding schema versioning and usage in react-native-navigation (HOC)

Hi everyone,

I had a question regarding the schema versioning functionality in combination with react-native-navigation.

At the moment, I have an async function as described in the documentation:

const SCHEMA_VERSION = '1';
const SCHEMA_VERSION_KEY = 'apollo-schema-version';

const setupClient = async () => {
  // server endpoint
  const uri = Platform.OS === 'ios' ? 'http://localhost:4000' : 'http://10.0.2.2:4000';

  const httpLink = createHttpLink({
    uri,
  });

  // authentication
  const authMiddleware = setContext(async () => {
    const token = await AsyncStorage.getItem('token');

    return {
      headers: {
        Authorization: token ? `Bearer ${token}` : '',
      },
    };
  });

  const httpLinkWithAuth = concat(authMiddleware, httpLink);

  // cache
  const cache = new InMemoryCache({
    addTypename: true,
  });

  const persistor = new CachePersistor({
    cache,
    storage: AsyncStorage,
  });

  const currentVersion = await AsyncStorage.getItem(SCHEMA_VERSION_KEY);

  if (currentVersion === SCHEMA_VERSION) {
    // If the current version matches the latest version,
    // we're good to go and can restore the cache.
    await persistor.restore();
  } else {
    // Otherwise, we'll want to purge the outdated persisted cache
    // and mark ourselves as having updated to the latest version.
    await persistor.purge();
    await AsyncStorage.setItem(SCHEMA_VERSION_KEY, SCHEMA_VERSION);
  }

  // local state
  const stateLink = withClientState({ resolvers, cache, defaults });

  return new ApolloClient({
    link: ApolloLink.from([stateLink, httpLinkWithAuth]),
    cache,
  });
};

However, when working with react-native-navigation I also need to have an HOC that is used to wrap all the separate screens I declare, like so:

export const withProvider = (Component: React.ComponentType) => {
  const WrappedComponent = (props: object) => (
    <ApolloProvider client={client}>
      <Component {...props} />
    </ApolloProvider>
  );

  return WrappedComponent;
};

As you can see, it needs the client in there as well.

So my question is, what is the best way to add the client to the HOC. When doing it synchronously, it didn't pose problems but now that I have a asynchronous function, I'm not sure what I should do.

I could change the code in the HOC to have an asynchronous componentWillMount, where it waits for the client. But I'm not sure if that is optimal since it will do that for all screens while the client needs to be setup asynchronously only once.

Are there any other solutions I am missing here?

Thanks a lot!

My SOLUTION: For devs having issue when the cache is not persistant. [React Native]

const cache = new InMemoryCache()
const client = new ApolloClient({
  uri: "http://192.168.0.106:4000",
  cache,
  defaultOptions
})

persistCache({
  cache: client.cache, // Try adding cache like this.
  storage: AsyncStorage,
  trigger:'write',
  debug: true,
});

when we add

persistCache({
  cache, 
  storage: AsyncStorage,
  trigger:'write',
  debug: true,
})

There are 2 cache instances. The client.cache is different from persistCache.
I have no idea why it works this way.

Component does not show persisted data on first render, but it does show it after an update

I added apollo-cache-persist to a todo app, but it does not show persisted data when the app starts. The thing is that I checked the apollo dev tools and the data got persisted and restored correctly, but it does not get reflected in the UI. The restored data does get reflected in the UI after I update the app (add a todo).

persist-bug

Here is the repo, and here is a codesandbox with the todo app.

Is there something wrong about how I configured apollo-cache-persist? Here is the commit which added it, I used persistCache.

persistCache({
      cache,
      storage: window ? window.localStorage : global.localStorage
});

Cache is not invalidated based on @cacheControl ?

So checking the localstorage state I noticed that there are no timestamps or cache-control information in the cache at all. It seems like apollo-client cache is not aware of this information and is not properly invalidating data based on how old it is.

I also noticed that even if I set fetchPolicy="no-cache" in Query the component will still render with the cached data before making the request and showing the new data. It is arguable if this is good behaviour or not, but I believe if the data is stale it should not be shown.

This is not that big of an issue for InMemoryCache as it is cleared when you reload the page, but if you persist the cache is completely breaks the page for users after a period.

persistCache promise never resolves

  • good first issue

So i have the following function to setup my Apollo Client

export async function createClient() {
  const cache = new InMemoryCache()

  // @ts-ignore
  await persistCache({
    cache,
    storage: AsyncStorage,
    debug: true
  })
  const bearerLink = setContext((_, { headers, cache }) => {
    const {
      AuthState: { token }
    } = cache.readQuery({ query: getToken })

    return {
      headers: {
        ...headers,
        authorization: token ? `Bearer ${token}` : ''
      }
    }
  })

  const resolvers = merge(AuthResolver, UserResolver)

  const defaults = { AuthState, UserState }

  const stateLink = withClientState({
    cache,
    resolvers,
    defaults
  })

  return new ApolloClient({
    link: ApolloLink.from([
      stateLink,
      bearerLink,
      new HttpLink({
        uri:
          'https://oqegglk3l4.execute-api.us-east-1.amazonaws.com/dev/graphql'
      })
    ]),
    cache
  })
}

And the following bootstrap file

export default class App extends React.Component<{}, { ready: boolean }> {
  client: any
  constructor() {
    // @ts-ignore
    super()
    this.state = {
      ready: false
    }
  }
  async componentDidMount() {
    this.client = await createClient()
    this.setState({ ready: true })
  }
  render() {
    const { ready } = this.state
    return ready ? (
      <ApolloProvider client={this.client}>
        <BuddiesNavigation />
      </ApolloProvider>
    ) : null
  }
}

But for some reason the promise this.client = await createClient() never gets resolved, and the app get's stuck.

I'm using Android.

typescript incompatible type with window.localStorage

I am getting an error when using typescript that says the localStorage type is not compatible. I have searched the issues and found #17 but that seems to be unrelated as far as I can tell.

here is what I am doing

const persistor = new CachePersistor({
  cache,
  storage: window.localStorage,
  debug: true,
  });

and here is the error I am getting

Argument of type '{ cache: InMemoryCache; storage: Storage; debug: true; }' is not assignable to parameter of type 'ApolloPersistOptions<NormalizedCacheObject>'. Types of property 'storage' are incompatible. Type 'Storage' is not assignable to type 'PersistentStorage<PersistedData<NormalizedCacheObject>>'. Types of property 'setItem' are incompatible. Type '(key: string, value: string) => void' is not assignable to type '(key: string, data: PersistedData<NormalizedCacheObject>) => void | Promise<void>'. Types of parameters 'value' and 'data' are incompatible. Type 'PersistedData<NormalizedCacheObject>' is not assignable to type 'string'. Type 'null' is not assignable to type 'string'.

Cache expiration question

Hi folks, I use apollo-cache-persist on a mobile app and I'm looking for a solution to get data if it exists, from the cache, else get it from remote.
I am aware of apollo cache policy but the cache-first value is not really a good solution for me.

I have a simple product list, when I click on a row, the detail screen is displayed and a product request is fired, so the request result is stored is the cache.
Then, I go back to the detail list.
Imagine 5mn later, I update my back office to change the product price.
If i go back to my detail screen, the product data will never be updated if I use the cache-first policy and will be always updated if I use the cache-and-network policy

Is there a way to add a cache expiration, maybe in minutes or hours ?

Cleaner React implementation suggestion

Hi guys I wanted to talk a bit about https://github.com/apollographql/apollo-cache-persist#how-do-i-wait-for-the-cache-to-be-restored-before-rendering-my-app as this seems to be a common problem.

The solution looks straight forward, but not very elegant. I was thinking that we could use a "render props component" in the style of the new <Query /> and <Mutation /> components to make this more elegant. In fact, I've created such a component for my own needs - https://github.com/ovotech/async-reactor-ts though its a bit more generic than that.

I was thinking that I could write a PR with something like this but more specific to apollo, so it has a nicer interface, but don't know where such a component will go, since apollo-cache-persist does not know about React.

Typescript incompatible type when using window.localstorage as storage

Issue: Typescript types check fails when using localstorage as storage for persistCache using the following example:

const cache = new InMemoryCache();
persistCache({
  cache, 
  storage: localStorage
});

error:

[ts]
Argument of type '{ cache: InMemoryCache; storage: Storage; }' is not assignable to parameter of type 'ApolloPersistOptions<NormalizedCacheObject>'.
  Types of property 'storage' are incompatible.
    Type 'Storage' is not assignable to type 'PersistentStorage<PersistedData<NormalizedCacheObject>>'.
      Types of property 'getItem' are incompatible.
        Type '(key: string) => string | null' is not assignable to type '(key: string) => Promise<PersistedData<NormalizedCacheObject>>'.
          Type 'string | null' is not assignable to type 'Promise<PersistedData<NormalizedCacheObject>>'.
            Type 'null' is not assignable to type 'Promise<PersistedData<NormalizedCacheObject>>'.
var localStorage: Storage

Typescript version: 2.6.2
tsconfig.json file inclues "lib": ["esnext", "dom"],

EDIT: Typescript fails because localStorage functions don't return Promises, while the PersistentStorage type functions return Promises.

Persisted cache keeps on growing with each refresh

Hello,

I am pretty new to the GraphQL/Apollo thingy in general and I am having issues with the caching of the result of a query I am making.
The query takes a datetime as an argument and returns a bunch of statistics - whatever.
When the result is stored in the localStorage it looks like that: $ROOT_QUERY.statistics({"datetime":"2018-09-25T04:22:49.635Z"}):...

As you can see it is stored with the argument in the key which makes it creates a new one everytime I do a page refresh.

In the end I get something like this and my local storage quickly hits the limit.
screen shot 2018-09-25 at 15 27 53

It feels like there are multiple ways of going around this, but I wanted to understand the best practices and why it stored the arguments in the quey. Why not just leave it at $ROOT_QUERY.statistics? What are the proper ways of handling these kind of behaviours? Not sure if this is a common issue or something very specific here.

Thanks and cheers ๐Ÿ™

Cache actually does not persist my data

Hi all, first thanks for your watching.
I have some issues when use "apollo-cache-persist", hope someone can help.

  1. Follow the docs, I know that if I declare these code,
const cache = new InMemoryCache({...});
persistCache({
  cache,
  storage: AsyncStorage,
});
const client = new ApolloClient({
  cache,
  ...
});

By default, apollo auto persist and restore my data when i query, but in console, it just show
[apollo-cache-persist] No stored cache to restore many times although my query is success.

  1. Then I try to use CachePersistor instead to handle manually, it persist and restore my data fine, but in my data, it's empty, so I think variable cache when declare at first
    (const cache = new InMemoryCache({...})) is the problem, I log this cache and its data always empty although my query is success. Is this variable cache is empty, so CachePersistor can't persist my data?
    Any idea or maybe a simple code to demo are good to me.
    Thanks a lot!

Smarter purging

As far as I understand, we purge the cache once it reaches a certain size. Is there possibly a more intelligent way to do this? E.g. trim older queries, or is that impossible?

Setting the value of 'apollo-cache-persist' exceeded the quota

Hi, I'm having this exception Setting the value of 'apollo-cache-persist' exceeded the quota
and I already set maxSize to false for unlimited cache size but still getting this exception.

By the way I'm using localStorage

This is my cache persistor Object:

const persistor = new CachePersistor({
  cache,
  storage: window.localStorage,
  debug: true,
  maxSize: false
});

Access CachePersistor via ApolloProvider?

Just a best practice question I suppose. Is it possible to access the CachePersistor from anywhere lower down in a component tree, via a mechanism like ApolloProvider? Or is there some other neat way? Would be cool for when doing manual persist triggering. I've just used context for now.

[Clarification] Is cache scoped to instance

This is probably an obvious question, but I wanted to get clarification on caching in apollo and if it is scoped to the apollo-client instance it's passed to. So if one was to have multiple apollo-clients and wanted to use CachePersistor to purge the cache, it would only purge the cache for the particular cache it is scoped too, right? I just want to make sure that calling purge on one in-memory-cache only purges that particular instance's cache in the browser.

localForage and persistCache type collision

Following code produces a TypeScript error:

import localForage from 'localforage';
import { persistCache } from 'apollo-cache-persist';
import { InMemoryCache } from 'apollo-cache-inmemory';

const cache = new InMemoryCache();


persistCache({
  cache,
  storage: localForage,
});

src/shared/apollo.ts:10:14 - error TS2345: Argument of type '{ cache: InMemoryCache; storage: LocalForage; }' is not assignable to parameter of type'ApolloPersistOptions<NormalizedCacheObject>'.
  Types of property 'storage' are incompatible.
    Type 'LocalForage' is not assignable to type 'PersistentStorage<PersistedData<NormalizedCacheObject>>'.
      Types of property 'setItem' are incompatible.
        Type '<T>(key: string, value: T, callback?: ((err: any, value: T) => void) | undefined) => Promise<T>' is not assignable to type '(key: string, data: PersistedData<NormalizedCacheObject>) => void | Promise<void>'.
          Type 'Promise<PersistedData<NormalizedCacheObject>>' is not assignable to type 'void | Promise<void>'.
            Type 'Promise<PersistedData<NormalizedCacheObject>>' is not assignable to type 'Promise<void>'.
              Type 'PersistedData<NormalizedCacheObject>' is not assignable to type 'void'.
                Type 'null' is not assignable to type 'void'.

10 persistCache({
                ~
11   cache,
   ~~~~~~~~
12   storage: localForage,
   ~~~~~~~~~~~~~~~~~~~~~~~
13 });
   ~

Need help: my app's cache is not persisted

Following is my code:

import React 	from "react"
import ReactDOM from "react-dom"

import ApolloClient, { gql } 	   from 'apollo-boost'
import { ApolloProvider, graphql } from 'react-apollo'

import { InMemoryCache } from 'apollo-cache-inmemory'
import { persistCache }  from 'apollo-cache-persist'

const q = gql`
	query {
		dog(breed: "bulldog") {
			id
			breed
			displayImage
		}
	}
`

const Main = graphql(q)(({data: { loading, error, dog }})=>{
	if (loading) return <p>Loading</p>
	if (error)   return <p>Error</p>

	return <p><img alt="" src={dog.displayImage} /></p>
})

const cache = new InMemoryCache()

persistCache({
	cache,
	storage: window.localStorage,
	debug: true,
}).then(() => {
	const client = new ApolloClient({
		uri: 'https://nx9zvp49q7.lp.gql.zone/graphql',
		cache
	})

	const App = () => (
		<ApolloProvider client={client}><Main /></ApolloProvider>
	)

	ReactDOM.render(<App />, document.getElementById("root"))
})

But I don't see anything in the localStorage in my browser (Chrome), am missing something?

Unvisited views causing it to crash

I'm having an issue where on my Home screen, I download a list of for example beers i.e.
{ id, beerName, beerPrice, beerRating etc }

[online]
Now when I click on the particular item it links to the page containing the data.

[offline]
If I click on a new item that I haven't previously visited then it causes the application to crash. Whereas links I've previously visited aren't causing it to crash. So it seems it is only caching the routes I visit.

How to use with Angular/Ionic?

Issue Labels

  • has-reproduction
  • feature
  • docs
  • blocking
  • good first issue

I'm trying to figure out how to use this with Angular/Ionic but can't seem to get it to work:

this.apollo.create({
	link: handleError.concat(auth).concat(link),
	cache: persistCache({
		cache: new InMemoryCache(),
		storage: localStorage,
	}),
});
Argument of type '{ link: ApolloLink; cache: Promise<void>; }' is not assignable to parameter of type 'ApolloClientOptions<{}>'.
  Types of property 'cache' are incompatible.
    Type 'Promise<void>' is not assignable to type 'ApolloCache<{}>'.
      Property 'read' is missing in type 'Promise<void>'.

Would also be nice if I could use Storage from @ionic/storage as the storage provider.

Cache filtering

One thing I would love to implement before we ship this officially is a cache filtering mechanism. I was talking about this with James and he suggested using graphql-anywhere to filter down the extracted store. What do you think?

Persist triggered on restore when trigger set to "write"

Does that make any sense? When I set the CachePersitor to "Write", i seem to get a persist right before the cache is restored.

import merge from "lodash.merge";
import localstate from "./localstate";
import { AsyncStorage, ActivityIndicator, View } from "react-native";
import React, { Component } from "react";
import { ApolloClient } from "apollo-client";
import { ApolloProvider } from "react-apollo";
import { ApolloLink } from "apollo-link";
import { HttpLink } from "apollo-link-http";
import { onError } from "apollo-link-error";
import { InMemoryCache } from "apollo-cache-inmemory";
import { CachePersistor } from "apollo-cache-persist";
import { withClientState } from "apollo-link-state";
import Config from "react-native-config";

const SCHEMA_VERSION = "4"; // Must be a string.
const SCHEMA_VERSION_KEY = "apollo-schema-version";

const cache = new InMemoryCache();

const persistor = new CachePersistor({
  cache,
  storage: AsyncStorage,
  debug: true,
  trigger: "write"
});

const stateLink = withClientState({ ...merge(localstate), cache });

const httpLink = new HttpLink({
  uri: Config.GRAPHQL_URL
});

const link = ApolloLink.from([stateLink, httpLink]);

class Apollo extends Component {
  state = {
    client: new ApolloClient({
      link,
      cache
    }),
    cacheRestored: false
  };
  async componentWillMount() {
    try {
      const currentVersion = await AsyncStorage.getItem(SCHEMA_VERSION_KEY);
      if (currentVersion === SCHEMA_VERSION) {
        // If the current version matches the latest version,
        // we're good to go and can restore the cache.
        console.log(`about to restore`);
        await persistor.restore();
        console.log(`cache restored`);
        this.setState({ cacheRestored: true });
      } else {
        // Otherwise, we'll want to purge the outdated persisted cache
        // and mark ourselves as having updated to the latest version.
        throw `Incorrect local cache schema version`;
      }
    } catch (error) {
      await persistor.purge();
      await AsyncStorage.setItem(SCHEMA_VERSION_KEY, SCHEMA_VERSION);
      this.setState({ cacheRestored: true });
    }
  }
  render() {
    return this.state.cacheRestored == true ? (
      <ApolloProvider client={this.state.client} {...this.props} />
    ) : (
      <View
        style={{
          flex: 1,
          justifyContent: "center",
          alignItems: "center"
        }}
      >
        <ActivityIndicator />
      </View>
    );
  }
}

export default Apollo;

The console log produces this:

about to restore
[apollo-cache-persist] Persisted cache of size 58
[apollo-cache-persist] Restored cache of size 58
cache restored

Let me know if I should dig in a bit further. I guess a restore is a "write" in a way, I set the debouce high ~3000 to make sure the restore is completed before the triggered write. With standard debounce, sometimes the write would execute first and wipe the cache.

It would be cool if restore didn't trigger a write however.

Help: How to silently do query in the background?

Hey!

I've just added this package to my project and it works great. I want to set it up to work this way but I don't know if it's possible:

  1. Do initial query
  2. The query is persisted into localStorage
  3. User closes the app
  4. User opens the app again
  5. Instead of seeing a loading spinner, the data is loaded from localStorage
  6. But, the query is still executed in the background, and if data is different, it gets replaced
  7. Persist new query again

Is this possible right now? I didn't see any option in the readme.

Thanks!

After adding to my project I get the following errors in VS code

[ts]File'../../tsconfig.base' does not exit

tsconfig.json file

  "extends": "../../tsconfig.base",
  "compilerOptions": {
    "rootDir": "./src",
    "outDir": "lib",
    "lib": ["es6", "dom", "es2017.object"]
  },
  "include": ["src/**/*.ts"],
  "exclude": ["src/**/__tests__/*.ts"]
}

my app is using

` "apollo-cache-inmemory": "^1.1.5",
    "apollo-cache-persist": "^0.1.1",
    "apollo-client": "^2.2.0",
    "apollo-link-http": "^1.3.2",
    "graphql": "^0.12.3",
    "graphql-tag": "^2.6.1",
    "normalize.css": "^7.0.0",
    "react": "^16.2.0",
    "react-apollo": "^2.0.4",
    "react-dom": "^16.2.0",
    "react-markdown": "^3.1.4",
    "react-router-dom": "^4.2.2",
    "react-scripts": "1.1.0",
    "react-tooltip": "^3.4.0",
    "styled-components": "^2.4.0",
    "webfontloader": "^1.6.28"`

and my index.js which is the only file I've changed since I've added 'apollo-cache-persist' is

import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';

import { ApolloClient } from 'apollo-client';
import { HttpLink } from 'apollo-link-http';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { ApolloProvider } from 'react-apollo'; 
import { persistCache } from 'apollo-cache-persist';

import App from './App';

const GRAPHCMS_API = 'https://api.graphcms.com/simple/v1/poop';

const client = new ApolloClient({
  link: new HttpLink({ uri: GRAPHCMS_API }),
  cache: new InMemoryCache()
});
persistCache({
  cache: client.cache,
  storage: window.localStorage
})

ReactDOM.render(
  <BrowserRouter>
    <ApolloProvider client={ client } >
      <App />
    </ApolloProvider>
  </BrowserRouter>
  , document.getElementById('root'));

` ``

No persistence when app closes

I first check the cache, then write to the cache, then check the cache again. The first time I check the cache I expect null, then after I expect 'abc'. When I close and reopen the app I expect the first cache check to be hydrated showing 'abc', but again I get null again.

import React from 'react';
import { AsyncStorage, ActivityIndicator, StyleSheet, Text, View } from 'react-native';
import { ApolloProvider, Mutation, Query, withApollo } from "react-apollo";
import ApolloClient from "apollo-boost";
import gql from "graphql-tag";
import { persistCache } from 'apollo-cache-persist';
import { InMemoryCache } from 'apollo-cache-inmemory';


const cache = new InMemoryCache();

persistCache({
  cache,
  storage: AsyncStorage,
});

const defaults = {
  currentUser: null
}

const typeDefs = `
type Query {
  currentUser: String
}
`;

const client = new ApolloClient({
  cache,
  uri: "...",
  clientState: {
    defaults,
    typeDefs
  }
});

const GET_USER = gql`
{
  currentUser @client
}
`;

client.query({query: GET_USER}).then((data)=>{
  console.log("before: ", data);
});
client.writeData({data: {currentUser: "abc"}});
client.query({query: GET_USER}).then((data)=>{
  console.log("after: ", data);
});

Any recommended limits on max size?

The default max cache size is 1MB. Is there a reason for this? Will performance of apollo client drop off when the cache gets arbitrarily bigger?

'write' trigger also on cache.reset()

Hi,
it seems from sources that on client.resetStore() we end up with cache.reset() so our patched method of cache.write() is probably not triggering.
If there is no observed query active, there will not be write operation and simple browser refresh would restore cache from storage for previous user even when we directly asked to invalidate it.

And I would probably consider handling it same way even in 'background' trigger.

Confused on how the cache is supposed to work

Hey there having an issue with apollo-boost and react native regarding local state. If i set local state for geo points and using react navigation I transition to another page the geo points are then set back to the defaults?

If i dont set defaults they dont reset but I get yellow box errors. Any ideas?

This library solves that issue, but do I need to use this library to solve it?

Option to synchronously restore cache

Can there be an option for persistCache to work synchronously? For users that are using localStorage or sessionStorage, it would be nice to run persistCache to completion before instantiating the client, and export the client as a direct value, instead of a Promise.

trigger: 'background' on react-native behavior not as expected

I've observed the following behavior with the following setup in my react native app...

persistCache({
    cache,
    storage: AsyncStorage,
    trigger: 'background',
  });

unexpected behavior

  1. User A logs in
  2. User A sees their list of events (as expected)
  3. User A logs out (JWT token & 'apollo-persist-cache' keys are explicitly deleted from localstorage)
  4. User B logs in, expecting to see their list of events but instead sees User A's list. (unexpected)

NOTE: I'm pretty sure I tried both backgrounding the app and not backgrounding the app.

assessment

I tracked this down to the persistCache function. When I commented it out, everything worked great. I'm not sure where user A's data is being rehydrated from because I explicitly delete the 'apollo-persist-cache' key from localstorage. if I trigger on 'write' everything works as expected as well, so that's how I've left things for now, realizing it may be a performance problem. So far, I've not noticed any performance issue though.

Potential issue caching an object by _id field

I ran into this edge case when working on a dynamic component builder, this is just a rough preview of it's functionality. As you select fields that you would like on the component, the GraphQL query and resulting data from the database update to reflect your selections.

I noticed when selecting the ID (_id) field when the item is already cached without the _id field selected, the cache breaks and throws errors for that particular item. It seems like the cache will store an item differently if the actual data has the _id property within the selection set.

I could see this causing an issue for normal users if two queries use the same _id variable, but on one route includes the _id property in the selection set, and a query on another route doesn't. I'm probably going to use a custom cache persister, but wanted to let you know about this anyway.

Here is a YouTube video link for clarity. The issue is visible about 20 secs in, when the _id field is added in.

screen shot 2017-12-21 at 6 44 23 pm

Here's a link to part of the source code. Apologies, but can't release a full working version

Here is a copy of the error:

Store error: the application attempted to write an object with no provided id but the store already contains an id of BackupMonitor:5a3c5721ae08b284c4de251b for this object. The selectionSet that was trying to be written is:
BackupMonitor(_id: "5a3c5721ae08b284c4de251b") {
  PlanName
  CompanyName
  UserName
  UserID
  tenant_id
  __typename
} could not be cloned.
    at ApolloClient.hookLogger [as devToolsHookCb] (<anonymous>:14:14)
    at QueryManager.onBroadcast (http://localhost:3000/static/js/bundle.js:2526:27)
    at QueryManager../node_modules/apollo-client/core/QueryManager.js.QueryManager.broadcastQueries (http://localhost:3000/static/js/bundle.js:3612:14)
    at Object.next (http://localhost:3000/static/js/bundle.js:3652:31)
    at SubscriptionObserver.next (http://localhost:3000/static/js/bundle.js:117881:14)
    at http://localhost:3000/static/js/bundle.js:5682:76
    at Array.forEach (<anonymous>)
    at Object.next (http://localhost:3000/static/js/bundle.js:5682:43)
    at SubscriptionObserver.next (http://localhost:3000/static/js/bundle.js:117881:14)
    at Object.next (http://localhost:3000/static/js/bundle.js:6987:34)
    at SubscriptionObserver.next (http://localhost:3000/static/js/bundle.js:117881:14)
    at http://localhost:3000/static/js/bundle.js:8558:81
    at retry (http://localhost:3000/static/js/bundle.js:8554:17)
    at Object.next (http://localhost:3000/static/js/bundle.js:8558:21)
    at SubscriptionObserver.next (http://localhost:3000/static/js/bundle.js:117881:14)
    at http://localhost:3000/static/js/bundle.js:8406:26
    at <anonymous>
VM48:17 DOMException: Failed to execute 'postMessage' on 'Window': Error: Error writing result to store for query:
 {
  BackupMonitor(_id: "5a3c5721ae08b284c4de251b") {
    PlanName
    CompanyName
    UserName
    UserID
    tenant_id
    __typename
  }
}

Cache object mutation

Hi,

would not be better to stop mutating cache object and just return the wrapped version?
Current API is kinda triggering people practising functional programming.

[Question] How to entirely clear client cache?

I'd like to completely clear the cache (stored in localStorage) after a user logs out but I can't find anything in the apollo docs.
resetStore() seems to re activate all active queries, effectively restoring the data.

How to use with universal/isomorphic apps (NextJS)

I've been playing around a little getting this to work with Nextjs and localStorage, specifically with the with-apollo example, with no luck.
The gist seems to be that the example initialises apollo twice. First on the server, and subsequently on the client, with the initial state set on the server. On the server, however localStorage is not available, hence I initialized on the client only, which seems to be the issue (localStorage is written to, but not rehydrated from):

import { InMemoryCache } from 'apollo-cache-inmemory';
import { persistCache } from 'apollo-cache-persist';

const cache = new InMemoryCache({...});

if (process.browser) {
  persistCache({
    cache,
    storage: window.localStorage,
  });
}

The question is, will this potentially never work in an universal app like NextJS, and what would be the alternatives? The README mentions that redux-persist-cookie-storage (which seems to cater for universal apps) could be used interchangeably, but I've had no luck using that either.

Error using create-react-app

Hi,
I'm trying to use apollo-cache-persist with the react and this is giving an error:
error

import React from 'react'
import ReactDOM from 'react-dom'

import { ApolloClient } from 'apollo-client'
import { HttpLink } from 'apollo-link-http'
import { InMemoryCache } from 'apollo-cache-inmemory'
import { ApolloProvider } from 'react-apollo'
 
import { persistCache } from 'apollo-cache-persist'

import './index.css'
import App from './App'
import registerServiceWorker from './registerServiceWorker'

const cache = new InMemoryCache({...})

const client = new ApolloClient({
   link: new HttpLink({
     uri: '',
     credentials: ''
   }),
   cache: cache
})

ReactDOM.render(
   <ApolloProvider client={client}>
     <App />
   </ApolloProvider>
, document.getElementById('root'))
registerServiceWorker()

I'm using create-react-app

Namespaced persistence

  • has-reproduction
  • feature
  • docs
  • blocking
  • good first issue

Hi! ^ Hope I did that right. I'm using web, so I'll use web terminology/concepts and hope it translates.

I'm considering using this to persist some data. However, I'd like to keep separate caches to keep the data separate. I'm not sure if this is a great architectural idea overall, but it's striking me as clean at the moment. I also might want to keep stuff in local storage that isn't from apollo cache. In order to persist it, I think the library will need to basically namespace it as separate keys in storage. Is this library capable of doing such a thing? And, if so, how?

Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.