Can I use a function with async await inside ComponentDidMount in React Native? - react-native

I am using AsyncStorage.getItem in React Native.
As soon as the Application loads, I want to get the saved data in the device memory using AsyncStorage.getItem. I thought of using ComponentDidMount(). So as soon as the components are loaded, I want to run the AsyncStorage.getItem automatically and save the data to the array DATA. This way the user will not push any button to start rendering what is saved on the memory of the device.
I used the code below, but I do not see any console.log activity. But the console.log works on my other pages on same program here. It seems the ComponentDidMount() did not get executed.
Thanks!
componentDidMount(){
async () => {
try {
const HomeData = await AsyncStorage.getItem('#MyApp_Homekey')
return HomeData
} catch (e) {
console.log('There was error.')
}
if(!HomeData){
console.log('There are no Dimmer Light saved in the memory.')
}
else {
console.log('There is value in data after getItem.')
this.setState(DATA = HomeData)
}
}

As metioned in comment you should use async for componentDidMount as:-
componentDidMount = async () => {
const HomeData = await AsyncStorage.getItem('#MyApp_Homekey')
if(!HomeData){
console.log('There are no Dimmer Light saved in the memory.')
}
else {
console.log('There is value in data after getItem.')
this.setState(DATA = HomeData)
}
}

Related

How to call API inside expo SplashScreen?

I'm new in react native so I can't figure out how to add an API call inside SplashScreen in react -native app. The context - I'm building a react-native app expo, which on app load should send API GET request to the backend to get order data, and based on that data I'm either displaying screen A(delivered) or B(order on it's way). I want to add this API call inside the SplashScreen when app still loads so when app is loaded there is no delay in getting API data and displaying screen A/B.
I have a simple useEffect function to call API like this:
const [data, setData] = useState{[]}
useEffect(() => {
const getData = async () => {
try {
const response = await axios.get(url);
if (response.status.code === 200 ) {
setData (response.data) // to save data in useState
}
} else if (response.status.code != 200) {
throw new Error();
}
} catch (error) {
console.log(error);
}
};
getData();
}, []);
and then in the return:
if (data.order.delivered) {
return <ScreenA />
}
else if (!data.order.delivered) {
return <ScreenB />
else {return <ScreenC />}
The issue is that sometimes if API is slow, then after splash screen app has a white screen, or ScreenC can be seen. How can I call API in the splashscreen while app is loading and have a nicer ux?
you can make a custom hook with simple UseState and put it after you've fetched your data
const [loading, setLoading] = useState(true)
...
useEffect(() => {
const getData = async () => {
try {
const response = await axios.get(url);
if (response.status.code === 200 ) {
setData (response.data)
// When data is ready you can trigger loading to false
setLoading(false)
}
...
and After that, you can use a Simple If statement on top of your app.js file
like this
if (!loaded) {
return <LoadingScreen/>; // whetever page you want to show here ;
}
you can use expo expo-splash-screen to achieve this goal:
call this hook on mount...
import * as SplashScreen from 'expo-splash-screen';
const [appIsReady, setAppIsReady] = useState(false);
useEffect(() => {
async function prepare() {
try {
// Keep the splash screen visible while we fetch resources
await SplashScreen.preventAutoHideAsync();
// Pre-load fonts, make any API calls you need to do here
await Font.loadAsync(Entypo.font);
// Artificially delay for two seconds to simulate a slow loading
// experience. Please remove this if you copy and paste the code!
await new Promise(resolve => setTimeout(resolve, 2000));
} catch (e) {
console.warn(e);
} finally {
// Tell the application to render
setAppIsReady(true);
}
}
prepare();
}, []);
you can also check expo doc

In which file do I set a key in react native async storage for the first time the app starts?

I am developing a react native app and I would like data persistence. Async storage is working fine as I expect it to, however the problem is that I initialize a key 'servers' in a component and and call the setItem function in componentDidMount function. Now because of this every time I terminate the app and run it again all the data from the previous session is removed as the 'servers' key is reset when the component is mounted. I understand why this is causing the problem so I want to know where should I set the key in my code that it will not reset on every time my component mounts.
This is the function that I call in componentDidMount. This is the only way to declare a key in Async storage correct? because without it I would not be able to call getItem.
const save = async () => {
try {
server_list = await AsyncStorage.setItem('server_list', JSON.stringify({servers: []}));
}
catch (e){
console.log("Failed to load")
}
}
You can achieve this by filling the AsyncStorage only as long as there is no data under the server_list key.
This would look like this:
setServerList = async (value) => {
try {
const serverList = await AsyncStorage.getItem('server_list');
if(serverList === null) {
await AsyncStorage.setItem('server_list', value)
}
} catch(e) {
// save error
}
console.log('Done.')
}
You can still call this in the componentDidMount and your server list will no longer be overwritten

local storage variables are reinitialized when i quit the application

what i want to do is to show a dialog box when i open the app,but i want to condition this display to a variable stored in my app local storage.
this variable get initialized when i click on a button.
i'll explain my case:
when i click on my button i do call this function which store data in my local storage as follow:
storeDate = async () => {
try{
await AsyncStorage.setItem('#key',true)
}catch(e){
alert("an error has occured when s")
}
}
and in my componentDidMount, according to my #key variable i do display my dialog box or not, here is my code for doing that:
componentDidMount(){
// this alert is used to check my #key variable value
alert(this.getData());
if (this.getData() == true){
this.setState({
dialogVisible2:true
});
}
}
here is my getData function:
getData = async () =>{
try{
const value = await AsyncStorage.getItem('#key')
if (value !== null){
return value;
}
return "undefined";
}catch(e){
alert("an error has occured when retrieving data")
}
}
when i close the app and re-open it the alert returns me the following [ object Objecct].
can anyone tell me where i'm wrong.
The componentDidMount function runs first before data is obtained from Asyncstorage, so the value is imported.
So you can configure componentDidMount as a asynchronous system.
async componentDidMount(){
getdata = await this.getData()
alert(getdata);
if (getdata === true){
this.setState({
dialogVisible2:true
});
}
}

The code below AsyncStorage does not run

I am working on my first React Native app. I am trying to learn how AsyncStorage works, but I somehow can't make it work even though it is said to be simple.
I am trying to save the data to storage, whenever the store is updated.
The problem is that the code below the line:
"await AsyncStorage.setItem("TODOS", jTodo)" does not seem to run. I don't know what the problem is...
const unsubscribe = store.subscribe(save);
async function save(){
try {
const todos = store.getState().todos
console.log(todos)
const jTodo = JSON.stringify(todos)
await AsyncStorage.setItem("TODOS", jTodo)
console.log("saving 2: " + todos);
} catch (e) {
console.error('Failed to save todos.' + todos)
}
}
The same is the case when I try to load data from storage. Again the code below the line: "const jTodos = await AsyncStorage.getItem('TODOS')" does not seem to run.
async function load() {
try {
console.log("so far even better")
const jTodos = await AsyncStorage.getItem('TODOS')
const todos = JSON.parse(jTodos);
console.log(todos);
todos.map((todo) => this.props.addTodo(todo))
} catch (e) {
console.error('Failed to load todos.')
}
}
load();
I hope some of you can point out what the problem is! Thank you in advance!!
If you are using android there is known issues with it not working.
"cold boot" your emulator from android studio.
https://github.com/facebook/react-native/issues/14101

Get item from AsyncStorage in React Native

I have a list of companies in React Native.
When I click on one of those companies I get the url of the API that is used for selected company. Then I store it to AsyncStorage and then I show the login screen. The function is as follows:
selectCompany(data_url, e) {
AsyncStorage.setItem("data_url", JSON.stringify(data_url), () => this.props.login());
}
Then on login page if I click on sign in button I go to the onLogin function, the function is as follows:
onLogin: function() {
fetch(data.url + '/manager/api/v1/obtain-auth-token/', })
.then(function(body) {
return body.json();
}).then(function(json) {
.....
}).catch(function() {
....
});
},
And data.url comes from data.js file, and I try to get url from the data.js file as follows:
let data_url = AsyncStorage.getItem("data_url").then(json => JSON.parse(json));
module.exports = {
url: data_url,
.....
}
But it doesn't work. Any advice?
AsyncStorage is async, therefore data_url will not be defined until it's retrieved what its looking for, you would need to move the fetch into the promise thats returned from the get so it will run it once it's done getting the data. This might be one way you tackle it:
const data_url = () => AsyncStorage.getItem("data_url"); //change this into a function
module.exports = {
url: data_url,
.....
}
now inside your component...
onLogin: function() {
data.url().then((url) => {
fetch(JSON.parse(url) + '/manager/api/v1/obtain-auth-token/', })
.then(function(body) {
return body.json();
}).then(function(json) {
.....
}).catch(function() {
....
});
});
},
AsyncStorage.getItem is a promise and needs to await for response rather than accessing direct and the function calling it should be defined as async. Here is an example to retrieve from AsyncStorage..
export async function getAccessKey(){
let accessToken = await AsyncStorage.getItem(ACCESS_TOKEN);
return accessToken;
}