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

update examples, fix hooks example in readme #413

Merged
merged 4 commits into from
Jan 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 38 additions & 92 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ short debounce interval).
#### React Native

```js
import AsyncStorage from '@react-native-community/async-storage';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { InMemoryCache } from '@apollo/client/core';
import { persistCache, AsyncStorageWrapper } from 'apollo3-cache-persist';

Expand All @@ -42,6 +42,8 @@ const client = new ApolloClient({
});
```

See a complete example in the [React Native example](./examples/react-native/App.tsx).

#### Web

```js
Expand All @@ -64,6 +66,8 @@ const client = new ApolloClient({
});
```

See a complete example in the [web example](./examples/web/src/index.tsx).

### Additional Options

`persistCache` and the constructor for `CachePersistor` accept the following
Expand Down Expand Up @@ -223,7 +227,7 @@ If you found that stable version of supported provider is no-longer compatible,

#### Why is the 'background' trigger only available for React Native?

Quite simply, because mobile apps are different than web apps.
Quite simply, because mobile apps are different from web apps.

Mobile apps are rarely terminated before transitioning to the background. This
is helped by the fact that an app is moved to the background whenever the user
Expand All @@ -246,102 +250,44 @@ This library, like Apollo Client, is framework agnostic; however, since many
people have asked, here's an example of how to handle this in React. PRs with
examples from other frameworks are welcome.

##### React

```js
import React, { Component } from 'react';
import { ApolloProvider } from '@apollo/client/react';
import { InMemoryCache } from '@apollo/client/core';
import { persistCache, LocalStorageWrapper } from 'apollo3-cache-persist';

class App extends Component {
state = {
client: null,
loaded: false,
};

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

// Setup your Apollo Link, and any other Apollo packages here.

const client = new ApolloClient({
cache,
...
});

try {
// See above for additional options, including other storage providers.
await persistCache({
cache,
storage: new LocalStorageWrapper(window.localStorage),
});
} catch (error) {
console.error('Error restoring Apollo cache', error);
}

this.setState({
client,
loaded: true,
});
}

render() {
const { client, loaded } = this.state;

if (!loaded) {
return <div>Loading...</div>;
}

return (
<ApolloProvider client={client}>
{/* the rest of your app goes here */}
</ApolloProvider>
);
}
}
```
You can find all examples in the [examples](./examples/) directory.

##### React Using Hooks

```js
import React,{ useState, useEffect } from 'react';
import { ApolloClient } from 'apollo-client';
import { InMemoryCache } from '@apollo/client/core';
import { ApolloProvider } from "@apollo/react-hooks"
import { persistCache, LocalStorageWrapper } from 'apollo3-cache-persist';
import React, {useEffect, useState} from 'react';

import {ApolloClient, ApolloProvider,} from '@apollo/client';
import {InMemoryCache} from '@apollo/client/core';
import {LocalStorageWrapper, persistCache} from 'apollo3-cache-persist';

const App = () => {
const [client, setClient] = useState();

useEffect(() => {
async function init() {
const cache = new InMemoryCache();
await persistCache({
cache,
storage: new LocalStorageWrapper(window.localStorage),
})
setClient(
new ApolloClient({
cache,
}),
);
}

init().catch(console.error);
}, []);

const App: React.FC = () => {
const [client, setClient] = useState(undefined);
useEffect(() => {
const cache = new InMemoryCache({...});

const client = new ApolloClient({
cache,
...
});
const initData = {
{/* your initial data */}
};
cache.writeData({ data: initData })

// See above for additional options, including other storage providers.
persistCache({
cache,
storage: new LocalStorageWrapper(window.localStorage)
}).then(() => {
client.onResetStore(async () => cache.writeData({ data: initData }));
setClient(client);
});
return () => {};
}, []);
if (client === undefined) return <div>Loading...</div>;
return (
<ApolloProvider client={client}>
{/* the rest of your app goes here */}
</ApolloProvider>
);
return (
<ApolloProvider client={client}>
{/* the rest of your app goes here */}
</ApolloProvider>
);
};

export default App;
```

Expand Down
182 changes: 128 additions & 54 deletions examples/react-native/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,81 +8,155 @@
* @format
*/

import React, { useEffect, useState } from 'react';
import { SafeAreaView, StyleSheet, ScrollView, Text } from 'react-native';
import { ApolloClient, InMemoryCache } from '@apollo/client';
import { persistCache, AsyncStorageWrapper } from 'apollo3-cache-persist';
import AsyncStorage from '@react-native-community/async-storage';
import { gql } from '@apollo/client';
import React, {useCallback, useEffect, useState} from 'react';
import {
Button,
DevSettings,
SafeAreaView,
ScrollView,
StyleSheet,
Text,
View,
} from 'react-native';
import {
ApolloClient,
ApolloProvider,
gql,
InMemoryCache,
NormalizedCacheObject,
useQuery,
} from '@apollo/client';
import {AsyncStorageWrapper, CachePersistor} from 'apollo3-cache-persist';
import AsyncStorage from '@react-native-async-storage/async-storage';

import { Colors } from 'react-native/Libraries/NewAppScreen';
const launchesGQL = gql`
query LaunchesQuery {
launches(limit: 10) {
id
mission_name
details
launch_date_utc
}
}
`;

type LaunchesQuery = {
launches: {
id: string;
mission_name: string;
details: string;
launch_date_utc: string;
}[];
};

const Launches = () => {
const {error, data, loading} = useQuery<LaunchesQuery>(launchesGQL, {
fetchPolicy: 'cache-and-network',
});

if (!data) {
// we don't have data yet

if (loading) {
// but we're loading some
return <Text style={styles.heading}>Loading initial data...</Text>;
}
if (error) {
// and we have an error
return <Text style={styles.heading}>Error loading data :(</Text>;
}
return <Text style={styles.heading}>Unknown error :(</Text>;
}

return (
<ScrollView>
{loading ? (
<Text style={styles.heading}>Loading fresh data...</Text>
) : null}
{data.launches.map(launch => (
<View key={launch.id} style={styles.item}>
<Text style={styles.mission}>{launch.mission_name}</Text>
<Text style={styles.launchDate}>
{new Date(launch.launch_date_utc).toLocaleString()}
</Text>
</View>
))}
</ScrollView>
);
};

const App = () => {
const [currencies, setCurrencies] = useState([]);
const [error, setError] = useState('');
const [client, setClient] = useState<ApolloClient<NormalizedCacheObject>>();
const [persistor, setPersistor] = useState<
CachePersistor<NormalizedCacheObject>
>();

useEffect(() => {
async function init() {
const cache = new InMemoryCache();
await persistCache({
let newPersistor = new CachePersistor({
cache,
storage: new AsyncStorageWrapper(AsyncStorage),
debug: __DEV__,
trigger: 'write',
});
const client = new ApolloClient({
uri: 'https://48p1r2roz4.sse.codesandbox.io',
cache: new InMemoryCache(),
});
try {
const { data } = await client.query({
query: gql`
query GetRates {
rates(currency: "USD") {
currency
}
}
`,
});

//@ts-ignore type this
setCurrencies(data.rates);
} catch (e) {
setError(e.message);
}
await newPersistor.restore();
setPersistor(newPersistor);
setClient(
new ApolloClient({
uri: 'https://api.spacex.land/graphql',
cache,
}),
);
}

init();
}, []);

const clearCache = useCallback(() => {
if (!persistor) {
return;
}
persistor.purge();
}, [persistor]);

const reload = useCallback(() => {
DevSettings.reload();
}, []);

if (!client) {
return <Text style={styles.heading}>Initializing app...</Text>;
}

return (
<>
<SafeAreaView>
{error ? (
<Text style={{ padding: 16, fontWeight: 'bold' }}>{error}</Text>
) : (
<>
<Text style={{ padding: 16, fontWeight: 'bold' }}>
List of currencies
</Text>
<ScrollView
contentInsetAdjustmentBehavior="automatic"
style={styles.scrollView}>
{currencies.map((item: any, index: any) => (
//@ts-ignore type it
<Text key={item.currency + String(index)} style={{ padding: 16 }}>
{item.currency}
</Text>
))}
</ScrollView>
</>
)}
<ApolloProvider client={client}>
<SafeAreaView style={{...StyleSheet.absoluteFillObject}}>
<View style={styles.content}>
<Launches />
</View>
<View style={styles.controls}>
<Button title={'Clear cache'} onPress={clearCache} />
<Button title={'Reload app (requires dev mode)'} onPress={reload} />
</View>
</SafeAreaView>
</>
</ApolloProvider>
);
};

const styles = StyleSheet.create({
scrollView: {
backgroundColor: Colors.lighter,
heading: {
padding: 16,
fontWeight: 'bold',
},
item: {
padding: 16,
},
mission: {},
launchDate: {
fontSize: 12,
},
content: {flex: 1},
controls: {flex: 0},
});

export default App;
2 changes: 1 addition & 1 deletion examples/react-native/android/gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@ android.useAndroidX=true
android.enableJetifier=true

# Version of flipper SDK to use with React Native
FLIPPER_VERSION=0.37.0
FLIPPER_VERSION=0.54.0
Loading