Failed in retrieve data from AsyncStorage - react-native

I am a beginner at react-native.
I trying to retrieve data that stored from screen1.js in Screen2.js but I failed.
I have import Asyncstorage from react-native for both .js
This how I store variable from screenone.js :
class screenone extends Component {
state = {
oldpin: '000000',
newpin: '',
secpin: '',
};
onPressButton = () => {
if (this.state.newpin == this.state.secpin) {
this.setState(
{ oldpin: this.state.newpin },
async() => await this.storeData());
}
else {
ToastAndroid.show("Password Unmatched", ToastAndroid.SHORT);
}
}
storeData = async () =>{
const {oldpin} = this.state;
let pin : oldpin;
try{
await AsyncStorage.setItem('mypin',pin);
ToastAndroid.show("Password Changed", ToastAndroid.SHORT);
}
catch (err){
console.warn(err)
}}
....
This is how I trying to retrieve data in screentwo.js:
class screentwo extends Component {
constructor(props) {
super(props);
this.onComplete = this.onComplete.bind(this);
this.state = {
pin: ''
};
}
retrieveData = async (mypin) => {
try {
let value = await AsyncStorage.getItem(mypin);
if (value !== null) {
console.log(value);
this.setState({
pin: value})
}
} catch (error) {
console.warn(err)
}
}
onComplete(inputtedPin, clear) {
retrieveData();
if (inputtedPin !== this.state.pin) {
ToastAndroid.show("Incorrect Pin", ToastAndroid.SHORT);
clear();
} else {
ToastAndroid.show("Pin is correct", ToastAndroid.SHORT);
clear();
this.props.navigation.navigate("Dashboard");
}}
....
Error:
Reference Error: ReferenceError:Can't find variable:retrieveData
Am I using the right way to stored and retrieve data?
Any suggestion?
Thank you.

There are a couple of issues that I can see with your code.
Firstly the retrieveData() function. It is asynchronous and should be called with await also you are getting the error: Reference Error: ReferenceError:Can't find variable:retrieveData because you haven't used this
So ideally you should call it await this.retrieveData();
There are a few more issues with this function. You use the parameter mypin but don't seem to pass any parameter to the function when you call it. Fixing this issue you should call retreiveData() like this:
await this.retrieveData('mypin');
Or you could remove passing the paramater altogether, which I will show how to do in my refactor below.
Finally you call retreiveData every time you check the inputtedPin this isn't that efficient, it is asynchronous so it may take some time, and secondly it also takes time for the setState function to complete, which means that the state may not have updated in time when you go to check it against the inputtedPin, meaning that you are checking the inputtedPin against the wrong value.
Code Refactor
This is how I would refactor your component.
Refactor retrieveData so that it no longer takes a parameter and the key is hardcoded in the .getItem
In the componentDidMount get the value of the pin from AsyncStorage and save it to state.
Remove the retrieveData call from onComplete
Here is the refactor
retrieveData = async () => { // parameter have been removed
try {
let value = await AsyncStorage.getItem('mypin'); // notice I am now passing the key as a string not as a parameter
if (value !== null) {
console.log(value);
this.setState({ pin: value })
}
} catch (error) {
console.warn(err)
}
}
// here we call the refactored retrievedData which will set the state.
async componentDidMount () {
await this.retrieveData();
}
onComplete(inputtedPin, clear) {
// we remove the call to retrieveData as we have already gotten the pin in the componentDidMount
if (inputtedPin !== this.state.pin) {
ToastAndroid.show("Incorrect Pin", ToastAndroid.SHORT);
clear();
} else {
ToastAndroid.show("Pin is correct", ToastAndroid.SHORT);
clear();
this.props.navigation.navigate("Dashboard");
}
}

only replace
retrieveData();
to
this.retrieveData();

When you call async method from a caller method that method also become async Try prefix
async onComplete () { await this.retrieveData() }

Related

AsyncStorage functions just producing garbage in react native

So I implemented this code in a file from the react native docs.
class Storage {
//store data in 'key'
store = async (key, data) => {
try {
await AsyncStorage.setItem(key, data);
} catch (error) {
// Error saving data
console.log(error.message);
}
};
retrieve = async (key) => {
try {
const value = await AsyncStorage.getItem(key);
if (value !== null) {
// We have data!!
console.log(value);
}
} catch (error) {
// Error retrieving data
console.log(error.message);
}
};
}
And this in other I want to use to actually store and retrieve the variables:
strg.store('test', 'testing');
testing = strg.retrieve('test');
I kept getting an error but then looking it up here I figured out my storage output was an object and not a string as I expected. So I used JSON.stringify(***) and this gibberish came out instead of a "testing".
{"_40":0, "_65":0, "_55":null,"_72":null}
edit: I figure out how to use the console to debug and I found out the 'testing' was inside the promise object that comes out of my function. I read a little about async functions and now I want to know how do I extract the values from the promises?
This happened because you are using AsyncStorage - an asynchronous storage system. You have to wait until it done retrieve data from storage to get the proper data.
I think there are two correct ways to get data from your implementation:
Use async with your container function name & await with your function called
async function getData() {
....
let data = await strg.retrieve('test');
console.log("data", data);
}
or simple use .then():
strg.retrieve('test').then((data) => {
console.log("data", data);
// Handle retrieved data
});
Hope that help. :)
This is how i did it and it works like a charm
import { AsyncStorage } from 'react-native';
module.exports = {
retrieve: async (value) => {
try {
let data = await AsyncStorage.getItem(value);
return data;
} catch (err) {
return err;
}
},
store: async (key, value) => {
try {
// stringify the value since value can only be string.
if (typeof (value) === 'object')
value = JSON.stringify(value)
return await AsyncStorage.setItem(key, value);
} catch (err) {
console.log(err)
return err;
}
}
}
Your store and retrieve functions are asyn so you have to use await until the actual task is complete.
So the code should be like below.
await strg.store('test', 'testing');
const testing = await strg.retrieve('test');
The garbage value is a promise so it will be something like the object you got.
If you return value like this you will retrieve it from outside.
const value = await AsyncStorage.getItem(key);
if (value !== null) {
// We have data!!
console.log(value);
return value;
}

AsyncStorage has weird characters in React-Native

I'm trying to store my users authorization key using AsyncStorage but whenever I do I get weird characters. Here is my relevant code:
async function retrieveItem(key) {
try {
let retrievedItem = await AsyncStorage.getItem(key).then(value => retrieveItem = value);
return retrievedItem;
} catch (error) {
console.log(error.message);
}
return
}
let test = retrieveItem('#authentication')
class AppNavigation extends Component {
render() {
console.log(test)
...
This is the output that I get for test. The item that I want is there under _55 and I'm able to get it by doing console.log(test._55). I just wanted to make sure I am not doing this correctly. Will the key always be _55 for async storage?
{"_40": 0, "_55": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI1ZTk1ODM3NDJlZDI1YjAxMWM4MWFiNWEiLCJpYXQiOjE1ODY4NTY4MjB9.yK0WYuZj7_2Nih7phisi5rmm0y7gF__PMRMEAafIkFk", "_65": 1, "_72": null}
You should note use async/await and .then together, both do the same thing.
Try this code instead:
async function retrieveItem(key) {
try {
let retrievedItem = await AsyncStorage.getItem(key);
return retrievedItem;
} catch (error) {
console.log(error.message);
}
return
}
let test = await retrieveItem('#authentication')
class AppNavigation extends Component {
render() {
console.log(test)
Edit: the object you got is a promise and you can get its value by doing the async/await syntax or calling .then(...)
its actually Promise Pointer you have to resolve the Promise by await
use it in classes
async componentDidMount() {
let test =await retrieveItem('#authentication');
console.log(test);
}
use it in hooks
useEffect(async () => {
let test =await retrieveItem('#authentication');
console.log(test);
});

How to use async/await to retrieve value from AsyncStorage in react native by using function

I have created prefsManager.js - Use for storing and retrieve data from AsyncStorage but I have faced a problem like when print log it return always undefined because of it is Async but I want to print the actual value in a log by the call of the function.
import { AsyncStorage } from 'react-native';
import prefskey from '../utils/constants/prefskeys';
const setValue = async (key, value) => {
await AsyncStorage.setItem(key, value);
}
const getValue = async (key) => {
let value = '';
try {
value = await AsyncStorage.getItem(key) || 'none';
} catch (error) {
// Error retrieving data
console.log(error.message);
}
return value;
};
const prefsmanager = {
setValue,
getValue
}
export default prefsmanager;
I have used this in my Home.js when button press I'm calling this method.
_handlePress() {
await prefsManager.setValue(prefskey.username, this.state.username)
console.log("username =>>", await prefsManager.getValue(prefskey.username));
}
You need to use async keyword on your function like this.
import { AsyncStorage } from 'react-native';
import prefskey from '../utils/constants/prefskeys';
const prefsnamager = {
setValue: function (key, value) {
AsyncStorage.setItem(key, value)
},
getValue: async (key) => {
let value = '';
try {
value = await AsyncStorage.getItem(key) || 'none';
} catch (error) {
// Error retrieving data
console.log(error.message);
}
return value;
}
}
export default prefsnamager;
calling function
_handlePress = () => {
prefsManager.setValue(prefskey.username, this.state.username)
console.log("username =>>" , prefsManager.getValue(prefskey.username));
}
Set value in storage
AsyncStorage.setItem('data','Read Data')
Get value from storage
constructor(props) {
super(props)
this.state = {};
let self=this;
//this function is called everytime , when you visit this screen.
this.__didFocusSubscription = this.props.navigation.addListener('didFocus',payload => {
AsyncStorage.getItem('data').then((value)=>{
if(value==null){
self.setState({count:'no data found'})
}
else{
self.setState({count:value})
}
})
});
}
Actually, it is like localStorage in the web but with a little difference. in getting the item it acts asynchronously. pay attention to below:
AsyncStorage.setItem('key', value);
But in getting it is like below:
AsyncStorage.getItem('key')
.then( value => console.log(value) );

Update Data from one to. another screen

hey guys I'm using a text field that can show my global variable value
when I update global variable ex:- global.xx++
it can't refresh when I click on it .how do I update data at once from many screen.. here's my ex
class A extend component
{
if(responseJson.responseCode == '200'){
++global.cartitems ;
Obj.onPress();
Obj.componentDidMount();
Alert.alert('SHOPPING','Item added successfully.',[{text: 'OK',},],{ cancelable: false })
}
class b extend component
{
<Text
style={{color:'white',textAlign:'center',fontSize:10}}
>{global.cartitems}</Text>
}
I believe what you meant is to pass a value from one screen to another.
You can either use AsyncStorage to keep the data inside your memory, or pass the data through props navigation
AsyncStorage example:
Store Data:
_storeData = async () => {
try {
await AsyncStorage.setItem('#MySuperStore:key', 'I like to save it.');
} catch (error) {
// Error saving data
}
}
Fetch Data:
_retrieveData = async () => {
try {
const value = await AsyncStorage.getItem('TASKS');
if (value !== null) {
// We have data!!
console.log(value);
}
} catch (error) {
// Error retrieving data
}
}
Passing data through props navigation:
First class:
<Button onPress = {
() => navigate("ScreenName", {name:'Jane'})
} />
Second class:
const {params} = this.props.navigation.state

How to remove an item from AsyncStorage in react-native

How to remove an item from AsyncStorage? right now I am trying this code:
AsyncStorage.removeItem('userId');
but this is not working for me.
Try this:
async removeItemValue(key) {
try {
await AsyncStorage.removeItem(key);
return true;
}
catch(exception) {
return false;
}
}
This is what I did, had a similar issue.It works well when you want to remove an item based on its id. make sure each item has a unique id.
remove_user = async(userid) => {
try{
let usersJSON= await AsyncStorage.getItem('users');
let usersArray = JSON.parse(usersJSON);
alteredUsers = usersArray.filter(function(e){
return e.id !== userid.id
})
AsyncStorage.setItem('users', JSON.stringify(alteredUsers));
this.setState({
users:alteredUsers
})
}
catch(error){
console.log(error)
}
};
This looks correct, but maybe you are trying to read back from AsyncStorage too soon? It's asynchronous, so the change isn't applied right away and you might still see the key if you try to get it on the following line. Try to call AsyncStorage.removeItem with await or do what you want to do in the callback.
this delete method which removes object from array by passing index (here i called id)
async deleteData(id) {
try {
this.state.item.splice(id, 1);
await AsyncStorage.setItem("mylist",JSON.stringify(this.state.item))
this.setState({ item: JSON.parse(await AsyncStorage.getItem("mylist")) })
} catch (error) {
console.log(error);
}
};
and call this by using onPress method, here i am using button and pass index
<Button onPress={this.deleteData.bind(this,index)}>delete</Button>
This is the framework code for AsyncStorage.removeItem:
removeItem: function(
key: string,
callback?: ?(error: ?Error) => void
): Promise {
return new Promise((resolve, reject) => {
RCTAsyncStorage.multiRemove([key], function(errors) {
var errs = convertErrors(errors);
callback && callback(errs && errs[0]);
if (errs) {
reject(errs[0]);
} else {
resolve(null);
}
});
});
}
As you can see above it requires the key(Which is name of the item you set in asyncstorage that you want to delete) and a callback function. Make sure you have the correct key and the correct params and it should work fine.
Use removeItem() method to remove values from AsyncStorage in react.
try {
await AsyncStorage.removeItem(key);
console.log('Data removed')
}
catch(exception) {
console.log(exception)
}
try this for react-native
const deletCar = async () => {
try {
await AsyncStorage.removeItem('#storage_Key').then(() => {
// props.navigation.navigate('same page name refresh ');
/* setprevCar({ carNumner: '', carModel: '' }) return empty obj if deleted. */
})
}
catch (exception) {
return false;
}
}
if you want to remove the selected list :-
let key =[
'visitorId',
'visitorMobile',
'visitorData',
]
await AsyncStorage.multiRemove(key)