Skip to content

Commit

Permalink
upgrades: SWR 1.3 for better optimisticUI interface, Expo v45, TypeSc…
Browse files Browse the repository at this point in the history
…ript deps
  • Loading branch information
zdmc23 committed May 7, 2022
1 parent fcd9bcd commit 782ab87
Show file tree
Hide file tree
Showing 5 changed files with 10,933 additions and 6,800 deletions.
128 changes: 67 additions & 61 deletions hooks/use-auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,75 +73,81 @@ const useCustomAuth = () => {
const { getSecureItem, setSecureItem, deleteSecureItem } = useSecureStore();

// rehydrate state from secure storage (depends on Redux to notify via "rehydrate" change)
useEffect(async() => {
/*
if auto-login, but accessToken is missing or invalid,
then attempt to rehydrate accessToken from secure storage
else do nothing bc user will be prompted to re-login
*/
if (isAutoLogin && (!accessToken || (accessToken && !validateToken(accessToken)))) {
// rehydrate access token
const rehydratedAccessToken = await getSecureItem(AuthConstants.ACCESS_TOKEN);
//console.log(`~~~~~~~~~~ rehydratedAccessToken: ${rehydratedAccessToken}`);
if (validateToken(rehydratedAccessToken)) setAccessToken(rehydratedAccessToken);
};
// rehydrate baseUrl
const rehydratedBaseUrl = baseUrl ?? (await getSecureItem(AuthConstants.BASE_URL));
//console.log(`~~~~~~~~~~ rehydratedBaseUrl: ${rehydratedBaseUrl}`);
setBaseUrl(rehydratedBaseUrl);
// rehydrate user
try {
const rehydratedUser = user ?? JSON.parse((await getSecureItem(AuthConstants.USER)));
//console.log(`~~~~~~~~~~ rehydratedUser: ${JSON.stringify(rehydratedUser)}`);
// TODO: if user unable to be rehydrated AND have valid accessToken and baseUrl, then request user info
setUser(rehydratedUser);
} catch (error) {
setUser(null);
};
useEffect(() => {
(async () => {
/*
if auto-login, but accessToken is missing or invalid,
then attempt to rehydrate accessToken from secure storage
else do nothing bc user will be prompted to re-login
*/
if (isAutoLogin && (!accessToken || (accessToken && !validateToken(accessToken)))) {
// rehydrate access token
const rehydratedAccessToken = await getSecureItem(AuthConstants.ACCESS_TOKEN);
//console.log(`~~~~~~~~~~ rehydratedAccessToken: ${rehydratedAccessToken}`);
if (validateToken(rehydratedAccessToken)) setAccessToken(rehydratedAccessToken);
};
// rehydrate baseUrl
const rehydratedBaseUrl = baseUrl ?? (await getSecureItem(AuthConstants.BASE_URL));
//console.log(`~~~~~~~~~~ rehydratedBaseUrl: ${rehydratedBaseUrl}`);
setBaseUrl(rehydratedBaseUrl);
// rehydrate user
try {
const rehydratedUser = user ?? JSON.parse((await getSecureItem(AuthConstants.USER)));
//console.log(`~~~~~~~~~~ rehydratedUser: ${JSON.stringify(rehydratedUser)}`);
// TODO: if user unable to be rehydrated AND have valid accessToken and baseUrl, then request user info
setUser(rehydratedUser);
} catch (error) {
setUser(null);
};
})();
}, [rehydrate]);

// when "accessToken" changes, validate it:
// if valid, configure axios interceptors and setAuthenticated(true)
// else setAuthenticated(false)
useEffect(async() => {
if (accessToken && validateToken(accessToken)) {
// Add a request interceptor
axios.interceptors.request.use(
config => {
if (accessToken && accessToken !== config.headers?.Authorization) {
config.headers["Authorization"] = `Bearer ${accessToken}`;
} else {
delete config.headers["Authorization"];
setAuthenticated(false);
};
return config;
},
error => error
);
// Add a response interceptor
axios.interceptors.response.use(
response => response,
async(error) => {
if (error?.response?.status === 401) {
setAuthenticated(false);
};
return Promise.reject(error);
}
);
setAuthenticated(true);
} else {
setAuthenticated(false);
};
useEffect(() => {
(async () => {
if (accessToken && validateToken(accessToken)) {
// Add a request interceptor
axios.interceptors.request.use(
config => {
if (accessToken && accessToken !== config.headers?.Authorization) {
config.headers["Authorization"] = `Bearer ${accessToken}`;
} else {
delete config.headers["Authorization"];
setAuthenticated(false);
};
return config;
},
error => error
);
// Add a response interceptor
axios.interceptors.response.use(
response => response,
async(error) => {
if (error?.response?.status === 401) {
setAuthenticated(false);
};
return Promise.reject(error);
}
);
setAuthenticated(true);
} else {
setAuthenticated(false);
};
})();
}, [accessToken]);

// when baseUrl changes, set axios default baseURL (if applicable)
useEffect(async() => {
if (baseUrl) {
if (baseUrl !== axios.defaults.baseURL) axios.defaults.baseURL = baseUrl;
} else {
setAuthenticated(false);
};
return;
useEffect(() => {
(async () => {
if (baseUrl) {
if (baseUrl !== axios.defaults.baseURL) axios.defaults.baseURL = baseUrl;
} else {
setAuthenticated(false);
};
return;
})();
}, [baseUrl]);

const toggleAutoLogin = () => dispatch(_toggleAutoLogin());
Expand Down
72 changes: 37 additions & 35 deletions hooks/use-import-contacts.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,45 +12,47 @@ const useImportContacts = ({ search }) => {
// TODO: use-list Contacts and exclude by title
const exclude = [];

useEffect(async() => {
try {
setLoading(true);
const { status } = await Contacts.requestPermissionsAsync();
setLoading(false);
if (status === 'granted') {
const importContactsList = [];
const { data } = await Contacts.getContactsAsync({});
data.map((contact) => {
const contactData = {};
if (contact.contactType === 'person') {
contactData['ID'] = contact.id;
contactData['title'] = contact.name;
if (contact.hasOwnProperty('emails') && contact.emails.length > 0) {
contactData['contact_email'] = [];
contact.emails.map((email, idx) => {
contactData['contact_email'].push({
key: `contact_email_${idx}`,
value: email.email,
useEffect(() => {
(async () => {
try {
setLoading(true);
const { status } = await Contacts.requestPermissionsAsync();
setLoading(false);
if (status === 'granted') {
const importContactsList = [];
const { data } = await Contacts.getContactsAsync({});
data.map((contact) => {
const contactData = {};
if (contact.contactType === 'person') {
contactData['ID'] = contact.id;
contactData['title'] = contact.name;
if (contact.hasOwnProperty('emails') && contact.emails.length > 0) {
contactData['contact_email'] = [];
contact.emails.map((email, idx) => {
contactData['contact_email'].push({
key: `contact_email_${idx}`,
value: email.email,
});
});
});
}
if (contact.hasOwnProperty('phoneNumbers') && contact.phoneNumbers.length > 0) {
contactData['contact_phone'] = [];
contact.phoneNumbers.map((phoneNumber, idx) => {
contactData['contact_phone'].push({
key: `contact_phone_${idx}`,
value: phoneNumber.number,
}
if (contact.hasOwnProperty('phoneNumbers') && contact.phoneNumbers.length > 0) {
contactData['contact_phone'] = [];
contact.phoneNumbers.map((phoneNumber, idx) => {
contactData['contact_phone'].push({
key: `contact_phone_${idx}`,
value: phoneNumber.number,
});
});
});
}
importContactsList.push(contactData);
}
importContactsList.push(contactData);
}
});
setImportContacts(importContactsList);
});
setImportContacts(importContactsList);
};
} catch (error) {
setError(error);
};
} catch (error) {
setError(error);
};
})();
}, []);

// filter any items marked to be excluded
Expand Down
11 changes: 0 additions & 11 deletions hooks/use-pin.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,17 +41,6 @@ const usePIN = () => {
return false;
};

/*
Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
at hooks/usePIN.js:48:12 in useEffect$argument_0
useEffect(async() => {
const validCNoncePIN = await isValidCNoncePIN();
// TODO:
//setValidCNoncePIN(validCNoncePIN);
setValidCNoncePIN(true);
}, [])
*/

const getPIN = async () => {
return getSecureItem(PINConstants.CODE);
};
Expand Down
Loading

0 comments on commit 782ab87

Please sign in to comment.