-
Notifications
You must be signed in to change notification settings - Fork 2
/
App.js
121 lines (107 loc) · 3.63 KB
/
App.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import React, { useEffect, useRef, useState } from 'react';
import { RootSiblingParent } from 'react-native-root-siblings';
import { SafeAreaProvider } from 'react-native-safe-area-context';
import { Provider as PaperProvider } from 'react-native-paper';
import AsyncStorage from '@react-native-async-storage/async-storage';
import AppLoading from 'expo-app-loading';
import { StatusBar } from 'expo-status-bar';
import PropTypes from 'prop-types';
import {
Provider as ReduxProvider,
useDispatch,
useSelector,
} from 'react-redux';
import { Navigation } from 'navigation';
import { CustomTheme } from 'theme';
import { loadToken, authenticate } from 'services/authSlice';
import { store } from 'services/store';
import { useLazyUserInfoQuery } from 'services/fridger/user';
import { setShoppingListYourProducts } from 'services/shoppingListYourProductsSlice';
// Main function:
const App = () => {
const [isLoading, setIsLoading] = useState(true);
return (
<RootSiblingParent>
<ReduxProvider store={store}>
{isLoading && <AppLoading />}
<AppContent isAppLoading={isLoading} setIsAppLoading={setIsLoading} />
</ReduxProvider>
</RootSiblingParent>
);
};
const AppContent = ({ isAppLoading, setIsAppLoading }) => {
const dispatch = useDispatch();
const token = useSelector((state) => state.auth.token);
const [fetchUserInfo, { isSuccess, isLoading, isUninitialized }] =
useLazyUserInfoQuery();
const isInit = useRef(true);
// Init post request to check if user is authenticated with token located in storage
useEffect(() => {
if (!isInit.current) return;
const initAuth = async () => {
const localToken = await AsyncStorage.getItem('token');
if (localToken) {
dispatch(loadToken(localToken));
}
fetchUserInfo();
};
initAuth();
isInit.current = false;
}, [fetchUserInfo]);
// Check if user is successfully authenticated and end app loading
useEffect(() => {
if (isUninitialized || isLoading) return;
if (isSuccess) {
dispatch(authenticate());
}
setIsAppLoading(false);
}, [isSuccess, isUninitialized, isLoading]);
// Update token in storage whenever value of it in redux changes
useEffect(() => {
const updateToken = async () => {
if (token) {
await AsyncStorage.setItem('token', token);
} else {
// Remove all data from provider (redux store):
dispatch(setShoppingListYourProducts({ value: {} }));
// Remove all data from local storage:
await AsyncStorage.multiRemove(['token', 'shoppingListsProducts']);
}
};
if (isUninitialized || isLoading) return;
updateToken();
}, [token, isUninitialized, isLoading]);
// Store shopping lists products in AsyncStorage
useEffect(() => {
AsyncStorage.getItem('shoppingListsProducts').then((obj) => {
if (obj) {
dispatch(setShoppingListYourProducts(JSON.parse(obj)));
}
});
const unsubscribe = store.subscribe(() => {
const shoppingListsProducts = JSON.stringify(
store.getState().shoppingListYourProducts
);
AsyncStorage.setItem('shoppingListsProducts', shoppingListsProducts);
});
return unsubscribe;
}, []);
// Render only if loaded:
if (isAppLoading) return null;
return (
<SafeAreaProvider>
<PaperProvider theme={CustomTheme}>
<StatusBar
style='light'
backgroundColor={CustomTheme.colors.richBlack}
/>
<Navigation />
</PaperProvider>
</SafeAreaProvider>
);
};
AppContent.propTypes = {
isAppLoading: PropTypes.bool.isRequired,
setIsAppLoading: PropTypes.func.isRequired,
};
export default App;