Skip to content

Commit 6226caf

Browse files
authored
Refactor/expo sdk 49 (#4)
* refactor: upgrade expo sdk to v49 and react query to v4 * fix: NetInfo and expo-font jest errors * chore: update react hooks lib * chore: upgrade msw * fix: tests and upgrade test libs * chore: upgrade graphql libs * doc: update readme
1 parent b86c6ef commit 6226caf

29 files changed

+8726
-6109
lines changed

App.tsx

+28-24
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import { NavigationContainer } from '@react-navigation/native';
33

44
import { StatusBar } from 'expo-status-bar';
55
import { ColorSchemeName, Platform, View, StyleSheet } from 'react-native';
6-
import { focusManager, QueryClientProvider } from 'react-query';
6+
import { focusManager, QueryClientProvider } from '@tanstack/react-query';
7+
import { PersistQueryClientProvider } from '@tanstack/react-query-persist-client';
78
import { Provider as PaperProvider } from 'react-native-paper';
89
import { SafeAreaProvider } from 'react-native-safe-area-context';
910
import { AppStateStatus } from 'react-native';
@@ -15,15 +16,13 @@ import { NetworkStatusProvider } from '@app/providers/NetworkStatusProvider';
1516
import { useOnlineManager } from '@app/hooks/useOnlineManager';
1617
import { GraphQLClientProvider } from '@app/providers/GraphQLClientProvider';
1718
import { queryClient } from '@app/services/queryClient';
19+
import { storagePersister } from '@app/services/persister';
20+
1821
import { MainStack } from '@app/navigation/MainStack';
1922
import { ThemeModeProvider } from '@app/providers/ThemeModeProvider';
2023
import { useCustomFonts } from '@app/hooks/useCustomFonts';
21-
import { initPersistor } from '@app/services/persistor';
2224
import { APP_NOT_READY } from '@app/test/testIDs';
2325

24-
// Load React Query cache from the async storage
25-
initPersistor(queryClient);
26-
2726
function onAppStateChange(status: AppStateStatus) {
2827
const isWEB = Platform.OS === 'web';
2928

@@ -59,26 +58,31 @@ export default function App() {
5958

6059
return (
6160
<GraphQLClientProvider>
62-
<QueryClientProvider client={queryClient}>
63-
<NetworkStatusProvider>
64-
<NavigationContainer theme={theme}>
65-
<PaperProvider theme={theme}>
66-
<ThemeModeProvider
67-
themeMode={themeMode}
68-
setThemeMode={setThemeModeState}
69-
themeModeState={themeModeState}
70-
>
71-
<StatusBar style={getStatusBarStyle(themeMode)} />
72-
<SafeAreaProvider
73-
style={{ backgroundColor: theme.colors.primary }}
61+
<PersistQueryClientProvider
62+
client={queryClient}
63+
persistOptions={{ persister: storagePersister }}
64+
>
65+
<QueryClientProvider client={queryClient}>
66+
<NetworkStatusProvider>
67+
<NavigationContainer theme={theme}>
68+
<PaperProvider theme={theme}>
69+
<ThemeModeProvider
70+
themeMode={themeMode}
71+
setThemeMode={setThemeModeState}
72+
themeModeState={themeModeState}
7473
>
75-
<MainStack />
76-
</SafeAreaProvider>
77-
</ThemeModeProvider>
78-
</PaperProvider>
79-
</NavigationContainer>
80-
</NetworkStatusProvider>
81-
</QueryClientProvider>
74+
<StatusBar style={getStatusBarStyle(themeMode)} />
75+
<SafeAreaProvider
76+
style={{ backgroundColor: theme.colors.primary }}
77+
>
78+
<MainStack />
79+
</SafeAreaProvider>
80+
</ThemeModeProvider>
81+
</PaperProvider>
82+
</NavigationContainer>
83+
</NetworkStatusProvider>
84+
</QueryClientProvider>
85+
</PersistQueryClientProvider>
8286
</GraphQLClientProvider>
8387
);
8488
}

README.md

+5-3
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ GraphQL subscription support example has been added.
2727

2828
## Requirements
2929

30-
- [Expo CLI](https://docs.expo.dev/workflow/expo-cli/) (SDK 42)
30+
- [Expo CLI](https://docs.expo.dev/workflow/expo-cli/) (SDK 49)
3131
- [Docker](https://docs.docker.com/desktop/)
3232
- [Docker Compose](https://docs.docker.com/compose/install/)
3333

@@ -121,10 +121,12 @@ To generate types and operations with GraphQL code generator (Hasura must be up)
121121
- [X] FlatList with infinite queries
122122
- [X] Cache persistence in the Async storage
123123
- [X] GraphQL subscriptions
124-
- [X] 100% test code coverage (`main` branch only)
124+
- [X] Test code coverage (`main` branch only)
125125

126-
## Branches
126+
## Branches with SDK 49
127127
- `main` Demo app with infinite list, async storage persistor and optimistic updates
128+
129+
## Branches with SDK 42
128130
- `simple-list` Demo app using a simple movies FlatList
129131
- `movies-list-optimistic-update` The movies list is optimistically updated after a movie mutation
130132
- `graphql-subscriptions` the movie details screen is updated with GraphQL subscriptions

__tests__/App.test.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React from 'react';
22
import { render } from '@testing-library/react-native';
33
import ReactNative, { AppStateStatus } from 'react-native';
4-
import { focusManager } from 'react-query';
4+
import { focusManager } from '@tanstack/react-query';
55

66
import App from '../App';
77
import * as appStateHook from '@app/hooks/useAppState';

__tests__/App.web.test.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React from 'react';
22
import { render } from '@testing-library/react-native';
33
import { AppStateStatus } from 'react-native';
4-
import { focusManager } from 'react-query';
4+
import { focusManager } from '@tanstack/react-query';
55

66
import App from '../App';
77
import * as appStateHook from '@app/hooks/useAppState';

jest.config.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ module.exports = {
1414
],
1515
moduleFileExtensions: ['js', 'ts', 'tsx'],
1616
transformIgnorePatterns: [
17-
'node_modules/(?!(jest-)?react-native|react-clone-referenced-element|@react-native-community|expo(nent)?|@expo(nent)?/.*|react-navigation|@react-navigation/.*|@unimodules/.*|unimodules|sentry-expo|native-base|@sentry/.*|crypto-es)',
17+
'node_modules/(?!((jest-)?react-native|@react-native(-community)?)|expo(nent)?|@expo(nent)?/.*|@expo-google-fonts/.*|react-navigation|@react-navigation/.*|@unimodules/.*|unimodules|sentry-expo|native-base|react-native-svg)',
1818
],
1919
moduleNameMapper: {
2020
'\\.(woff|woff2)$': require.resolve('./src/test/fileMock.js'),

package.json

+45-41
Original file line numberDiff line numberDiff line change
@@ -22,66 +22,70 @@
2222
"hasura:down": "cd hasura; docker-compose down",
2323
"hasura:logs": "cd hasura; docker-compose logs -f",
2424
"hasura:console": "cd hasura; hasura console",
25-
"hasura:arm64:up": "cd hasura; docker-compose -f docker-compose.yml -f docker-compose.arm64.yml up",
26-
"hasura:arm64:down": "cd hasura; docker-compose -f docker-compose.yml -f docker-compose.arm64.yml down",
27-
"hasura:arm64:logs": "cd hasura; docker-compose -f docker-compose.yml -f docker-compose.arm64.yml logs -f",
2825
"test": "jest",
2926
"test:silent": "jest --silent --detectOpenHandles --forceExit",
3027
"test:watch": "yarn test --watch",
3128
"test:coverage": "yarn test --coverage; open coverage/lcov-report/index.html"
3229
},
3330
"dependencies": {
34-
"@expo/vector-icons": "^12.0.0",
35-
"@react-native-async-storage/async-storage": "~1.15.0",
36-
"@react-native-community/netinfo": "6.0.0",
31+
"@babel/types": "^7.22.5",
32+
"@expo/cli": "^0.10.11",
33+
"@expo/vector-icons": "^13.0.0",
34+
"@expo/webpack-config": "^18.1.2",
35+
"@react-native-async-storage/async-storage": "1.18.2",
36+
"@react-native-community/netinfo": "^9.4.1",
3737
"@react-navigation/native": "^6.0.2",
3838
"@react-navigation/stack": "^6.0.7",
39-
"@testing-library/jest-native": "^3.4.3",
40-
"@testing-library/react-hooks": "^7.0.2",
41-
"@testing-library/react-native": "8.0.0-rc.0",
39+
"@tanstack/query-async-storage-persister": "^4.32.1",
40+
"@tanstack/query-sync-storage-persister": "^4.32.1",
41+
"@tanstack/react-query": "^4.32.1",
42+
"@tanstack/react-query-persist-client": "^4.32.1",
43+
"@testing-library/jest-native": "^5.4.2",
44+
"@testing-library/react-hooks": "^8.0.1",
45+
"@testing-library/react-native": "^12.2.0",
4246
"color": "^3.1.3",
43-
"expo": "^42.0.0",
44-
"expo-constants": "~11.0.1",
45-
"expo-font": "~9.2.1",
46-
"expo-status-bar": "~1.0.4",
47+
"expo": "^49.0.0",
48+
"expo-constants": "~14.4.2",
49+
"expo-font": "~11.4.0",
50+
"expo-status-bar": "~1.6.0",
4751
"graphql": "^15.5.0",
48-
"graphql-request": "^3.4.0",
49-
"msw": "^0.26.2",
50-
"react": "16.13.1",
51-
"react-dom": "16.13.1",
52+
"graphql-request": "^6.1.0",
53+
"msw": "^1.2.3",
54+
"react": "18.2.0",
55+
"react-dom": "18.2.0",
5256
"react-error-boundary": "^3.1.3",
53-
"react-native": "https://github.com/expo/react-native/archive/sdk-42.0.0.tar.gz",
54-
"react-native-gesture-handler": "~1.10.2",
55-
"react-native-paper": "^4.9.2",
56-
"react-native-reanimated": "~2.2.0",
57-
"react-native-safe-area-context": "3.2.0",
58-
"react-native-screens": "~3.4.0",
59-
"react-native-web": "~0.13.12",
60-
"react-query": "^3.32.3"
57+
"react-native": "0.72.3",
58+
"react-native-gesture-handler": "~2.12.0",
59+
"react-native-paper": "^4.12.4",
60+
"react-native-reanimated": "~3.3.0",
61+
"react-native-safe-area-context": "^4.7.1",
62+
"react-native-screens": "~3.22.0",
63+
"react-native-vector-icons": "^10.0.0",
64+
"react-native-web": "~0.19.6"
6165
},
6266
"devDependencies": {
63-
"@babel/core": "~7.9.0",
64-
"@callstack/eslint-config": "^10.1.0",
65-
"@expo/config": "^3.3.27",
66-
"@graphql-codegen/cli": "^2.3.0",
67-
"@graphql-codegen/typescript": "^2.4.0",
68-
"@graphql-codegen/typescript-graphql-request": "^4.3.0",
69-
"@graphql-codegen/typescript-operations": "^2.2.0",
70-
"@graphql-codegen/typescript-react-query": "^3.2.0",
67+
"@babel/core": "^7.20.0",
68+
"@callstack/eslint-config": "^13.0.2",
69+
"@expo/config": "~8.1.1",
70+
"@graphql-codegen/cli": "^5.0.0",
71+
"@graphql-codegen/typescript": "^4.0.1",
72+
"@graphql-codegen/typescript-graphql-request": "^5.0.0",
73+
"@graphql-codegen/typescript-operations": "^4.0.1",
74+
"@graphql-codegen/typescript-react-query": "^4.1.0",
7175
"@types/base-64": "^0.1.3",
7276
"@types/color": "^3.0.1",
7377
"@types/jest": "^26.0.24",
74-
"@types/react": "~16.9.35",
75-
"@types/react-dom": "~16.9.8",
78+
"@types/react": "~18.2.14",
79+
"@types/react-dom": "~18.0.10",
7680
"@types/react-native": "~0.63.2",
7781
"babel-jest": "~25.2.6",
7882
"babel-plugin-module-resolver": "^4.1.0",
79-
"eslint": "^7.32.0",
83+
"eslint": "^8.46.0",
8084
"eslint-import-resolver-alias": "^1.1.2",
81-
"eslint-plugin-prettier": "^4.0.0",
82-
"jest": "^26.4.2",
83-
"jest-expo": "^42.1.0",
84-
"prettier": "^2.3.2",
85-
"typescript": "~4.4.3"
85+
"eslint-plugin-prettier": "^5.0.0",
86+
"jest": "^29.6.2",
87+
"jest-expo": "^49.0.0",
88+
"prettier": "^3.0.0",
89+
"typescript": "^5.1.3"
8690
}
8791
}

src/hooks/__tests__/useAppState.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@ describe('useAppState hook tests', () => {
66
it('Should not call the app change handler', async () => {
77
const onAppChange = jest.fn().mockImplementation(() => void 0);
88
renderHook(() => useAppState(onAppChange));
9-
expect(onAppChange).not.toBeCalled();
9+
expect(onAppChange).not.toHaveBeenCalled();
1010
});
1111
});

src/hooks/__tests__/useCustomFonts.test.tsx

+1-6
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,7 @@ import { useCustomFonts } from '@app/hooks/useCustomFonts';
44

55
describe('useCustomFonts status hook tests', () => {
66
it('Should load the fonts', async () => {
7-
const { result, waitForNextUpdate } = renderHook(() => useCustomFonts());
8-
9-
expect(result.current[0]).toBeFalsy();
10-
11-
// Wait for the mocked fonts to be loaded
12-
await waitForNextUpdate();
7+
const { result } = renderHook(() => useCustomFonts());
138
expect(result.current[0]).toBeTruthy();
149
});
1510
});

src/hooks/__tests__/useNetworkStatus.test.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ describe('useNetworkStatus hook tests', () => {
2929
});
3030
const { result } = renderHook(() => useNetworkStatus());
3131

32-
expect(addEventListenerSpy).toBeCalled();
32+
expect(addEventListenerSpy).toHaveBeenCalled();
3333

3434
// Mock a connected event
3535
const connectedInfoStateMock: NetInfoState = {

src/hooks/__tests__/useOnlineManager.test.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { renderHook, act } from '@testing-library/react-hooks';
2-
import { onlineManager } from 'react-query';
2+
import { onlineManager } from '@tanstack/react-query';
33
import NetInfo from '@react-native-community/netinfo';
44
import {
55
NetInfoState,

src/hooks/__tests__/useRefreshByUser.test.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ describe('useRefreshByUser status hook tests', () => {
2525
});
2626

2727
// Should call the refetch function
28-
expect(refetchSpy).toBeCalled();
28+
expect(refetchSpy).toHaveBeenCalled();
2929

3030
// Should set isRefetchingByUser to true
3131
waitFor(() => expect(result.current.isRefetchingByUser).toBeTruthy());

src/hooks/__tests__/useRefreshOnFocus.test.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,12 @@ describe('useRefreshOnFocus status hook tests', () => {
3333
render(<Container />);
3434

3535
// Should not refetch on the first screen1 focus
36-
expect(refetchSpy).not.toBeCalled();
36+
expect(refetchSpy).not.toHaveBeenCalled();
3737

3838
await act(async () => navigation.current.navigate('screen2'));
3939

4040
// Should refetch on the second screen1 focus
4141
await act(async () => navigation.current.navigate('screen1'));
42-
expect(refetchSpy).toBeCalled();
42+
expect(refetchSpy).toHaveBeenCalled();
4343
});
4444
});

src/hooks/useAppState.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ import { AppState, AppStateStatus } from 'react-native';
33

44
export function useAppState(onChange: (appState: AppStateStatus) => void) {
55
useEffect(() => {
6-
AppState.addEventListener('change', onChange);
6+
const listener = AppState.addEventListener('change', onChange);
77
return () => {
8-
AppState.removeEventListener('change', onChange);
8+
listener.remove();
99
};
1010
}, [onChange]);
1111
}

src/hooks/useOnlineManager.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React from 'react';
22
import NetInfo from '@react-native-community/netinfo';
3-
import { onlineManager } from 'react-query';
3+
import { onlineManager } from '@tanstack/react-query';
44
import { Platform } from 'react-native';
55

66
export function useOnlineManager() {

0 commit comments

Comments
 (0)