Last active
September 22, 2022 05:15
-
-
Save thecodecafe/6ee3637ad7d569fdd4ebf7c4c60ead5f to your computer and use it in GitHub Desktop.
Async Storage Exercise
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, {useCallback, useEffect, useState} from 'react'; | |
import { | |
ActivityIndicator, | |
Alert, | |
Button, | |
StyleSheet, | |
Text, | |
View, | |
} from 'react-native'; | |
import AsyncStorage from '@react-native-async-storage/async-storage'; | |
import {IAppProps} from './interfaces'; | |
const EN: Record<string, string> = { | |
greeting: 'Hello', | |
alert_title: 'Select language', | |
alert_option_1_text: 'Set language to Spanish', | |
alert_option_2_text: 'Do nothing', | |
success_title: 'Success', | |
success_message: 'Idioma cambiado con éxito a español.', | |
button: 'Choose favorite color', | |
color_alert_title: 'Select a color', | |
color_alert_option_1: 'Orange', | |
color_alert_option_2: 'Green', | |
color_alert_cancel: 'Cancel', | |
no_color_selected: 'No color selected.', | |
}; | |
const ESP: Record<string, string> = { | |
greeting: 'Hola', | |
alert_title: 'Seleccione el idioma', | |
alert_option_1_text: 'Establecer idioma en inglés', | |
alert_option_2_text: 'Hacer nada', | |
success_title: 'Éxito', | |
success_message: 'Language successfully changed to English.', | |
button: 'Elige color favorito', | |
color_alert_title: 'Selecciona un color', | |
color_alert_option_1: 'Orange', | |
color_alert_option_2: 'Green', | |
color_alert_cancel: 'Cancelar', | |
no_color_selected: 'Ningún color seleccionado.', | |
}; | |
const App: IAppProps = function App() { | |
const [color, setColor] = useState<string>(); | |
const [language, setLanguage] = useState<string>(); | |
const [translation, setTranslation] = useState<Record<string, string>>(); | |
const handleChangeLanguage = useCallback(async () => { | |
// we will switch to the other language or maintain english if non is selected | |
const newLanguage = language === 'EN' ? 'ESP' : 'EN'; | |
// we will select a translation depending on what language is selected as new language | |
const newTranslation = newLanguage === 'EN' ? ESP : EN; | |
// store the new language in async storage | |
await AsyncStorage.setItem('LOCATION', newLanguage); | |
// find the selected language's favorite color in async storage | |
const languageColor = await AsyncStorage.getItem( | |
`FAVORITE_COLOR:${newLanguage}`, | |
); | |
// update state with new language | |
setLanguage(newLanguage); | |
// update state with language color | |
setColor(languageColor || undefined); | |
// update state with selected translation | |
setTranslation(newTranslation); | |
}, [language]); | |
const handleButtonPress = useCallback(() => { | |
// if translation is not set stop | |
if (!translation) { | |
return; | |
} | |
// ask user to switch language | |
Alert.alert(translation.alert_title, '', [ | |
{text: translation.alert_option_1_text, onPress: handleChangeLanguage}, | |
{text: translation.alert_option_2_text, style: 'cancel'}, | |
]); | |
}, [handleChangeLanguage, translation]); | |
const chooseColor = useCallback( | |
async (selectedColor: string) => { | |
// if language is not set stop | |
if (!language) { | |
return; | |
} | |
// save color of selected language in async storage | |
// Example: Selecting EN will result in the following async storage key FAVORITE_COLOR:EN | |
await AsyncStorage.setItem(`FAVORITE_COLOR:${language}`, selectedColor); | |
// update state with selected color | |
setColor(selectedColor); | |
}, | |
[language], | |
); | |
const handleChooseColor = useCallback(() => { | |
// if translation is not set stop | |
if (!translation) { | |
return; | |
} | |
// ask user to select color | |
Alert.alert(translation.color_alert_title, '', [ | |
{ | |
text: translation.color_alert_option_1, | |
onPress: () => chooseColor('Orange'), | |
}, | |
{ | |
text: translation.color_alert_option_2, | |
onPress: () => chooseColor('Green'), | |
}, | |
{text: translation.color_alert_cancel, style: 'cancel'}, | |
]); | |
}, [chooseColor, translation]); | |
const initialize = useCallback(async () => { | |
// get saved color at component initialization | |
const persistedLanguage: string | null = await AsyncStorage.getItem( | |
'LANGUAGE', | |
); | |
// check if a language was saved | |
if (persistedLanguage) { | |
// get the saved color for the saved language | |
const languageColor = await AsyncStorage.getItem( | |
`FAVORITE_COLOR:${persistedLanguage}`, | |
); | |
// update state with saved color | |
setColor(languageColor || undefined); | |
} | |
// update sate with saved language | |
setLanguage(persistedLanguage || 'EN'); | |
// update state with saved language's translation | |
setTranslation(persistedLanguage === 'ESP' ? ESP : EN); | |
}, []); | |
useEffect(function componentDidMount() { | |
// initialize component after 2 seconds (simulate an async call) | |
setTimeout(initialize, 2000); | |
return function componentWillUnmount() { | |
// do nothing for now | |
}; | |
// eslint-disable-next-line react-hooks/exhaustive-deps | |
}, []); | |
// render a loader if no translation has been set | |
if (!translation) { | |
return ( | |
<View style={styles.container}> | |
<ActivityIndicator | |
style={styles.contentLoader} | |
size="large" | |
color="#666666" | |
/> | |
</View> | |
); | |
} | |
// render content if translation has been set | |
return ( | |
<View style={styles.container}> | |
<Button title={translation.greeting} onPress={handleButtonPress} /> | |
<Button title={translation.button} onPress={handleChooseColor} /> | |
<Text style={styles.colorName}> | |
{color || translation.no_color_selected} | |
</Text> | |
</View> | |
); | |
}; | |
const styles = StyleSheet.create({ | |
colorName: { | |
textAlign: 'center', | |
marginVertical: 40, | |
}, | |
contentLoader: { | |
alignSelf: 'center', | |
}, | |
container: { | |
marginVertical: 100, | |
justifyContent: 'center', | |
paddingHorizontal: 24, | |
}, | |
}); | |
export default App; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
export type IAppProps = React.FC<{}>; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {createContext} from 'react'; | |
import {ILocationContext} from './interfaces'; | |
export const LocationContext = createContext<ILocationContext>({}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import AsyncStorage from '@react-native-async-storage/async-storage'; | |
import React, {useCallback, useEffect, useState} from 'react'; | |
import {ILocation, ILocationProviderProps, IWeatherReport} from './interfaces'; | |
import {LocationContext} from './LocationContext'; | |
const LocationProvider: ILocationProviderProps = function LocationProvider({ | |
children, | |
}) { | |
const [location, setLocation] = useState<ILocation>(); | |
const [weatherReport, setWeatherReport] = useState<IWeatherReport>(); | |
const initialize = useCallback(async () => { | |
// get saved color at component initialization | |
const persistedLocationRaw: string | null = await AsyncStorage.getItem( | |
'LOCATION', | |
); | |
// JSO parse weather report if found | |
const persistedLocation: ILocation | undefined = persistedLocationRaw | |
? JSON.parse(persistedLocationRaw) | |
: undefined; | |
// check if a language was saved | |
if (persistedLocation) { | |
// get the saved color for the saved language | |
const persistedWeatherReportRaw: string | null = | |
await AsyncStorage.getItem( | |
`FAVORITE_COLOR:${persistedLocation.country}:${persistedLocation.state}`, | |
); | |
// JSON part weather report if found | |
const persistedWeatherReport: IWeatherReport | undefined = | |
persistedWeatherReportRaw | |
? JSON.parse(persistedWeatherReportRaw) | |
: undefined; | |
// update state with saved color | |
setWeatherReport(persistedWeatherReport || undefined); | |
} | |
// update sate with saved language | |
setLocation(persistedLocation || undefined); | |
}, []); | |
useEffect(function componentDidMount() { | |
// initialize component after 2 seconds (simulate an async call) | |
setTimeout(initialize, 2000); | |
return function componentWillUnmount() { | |
// do nothing for now | |
}; | |
// eslint-disable-next-line react-hooks/exhaustive-deps | |
}, []); | |
return ( | |
<LocationContext.Provider | |
value={{ | |
location, | |
weatherReport, | |
setLocation, | |
setWeatherReport, | |
}}> | |
{children} | |
</LocationContext.Provider> | |
); | |
}; | |
export default LocationProvider; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
export type ILocationProviderProps = React.FC<{ | |
children: React.ReactNode; | |
}>; | |
export type ILocation = { | |
country: string; | |
state: string; | |
}; | |
export type IWeatherReport = any; | |
export type ILocationContext = { | |
location?: ILocation; | |
weatherReport?: IWeatherReport; | |
setLocation?: (location: ILocation) => void; | |
setWeatherReport?: (weatherReport: IWeatherReport) => void; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment