Cancel all asynchronous tasks in componentWillUnmount method react-native - react-native

Here is my code and I use asyncstorage to set user's name. I get this error
I get a warning saying Can't perform a React state update on an unmounted component. it indicates a memory leak. cancel and asynchronous tasks in the componentWillUnmount method.
UNSAFE_componentWillMount(){
this.getName()
this.disableSEND()
}
getName = async () => {
let value = 'userName'
try {
await AsyncStorage.setItem('NAME', value))
} catch (e) {
Alert.alert(e.message)
}
}
disableSEND = async () => {
let value = await AsyncStorage.getItem('SENDDISABLED')
this.setState({ switch: value == 'true' ? true : false })
let disableBtn = AsyncStorage.getItem('DISABLEBTN')
this.setState({ disableBtn: disableBtn == 'false' ? false : true })
}
disableMSG = async (value) => {
try {
AsyncStorage.setItem('DISABLEMSG', value.toString())
} catch (e) {
Alert.alert(e.message)
}
}
disableBtn = async (disableBtn) => {
try {
AsyncStorage.setItem('DISABLEBTN', disableBtn.toString())
} catch (e) {
Alert.alert(e.message)
}
}
render() {
return (
<DrawerContentScrollView {...this.props}>
</DrawerContentScrollView>
);
}
}
})

Related

React Native how get data from asynchrone function

I try to get data from an asynchronestorage function
_retrieveData = async () => {
var test = await AsyncStorage.getItem('myitem')
return test
}
_generateRandomCards() {
console.log(this._retrieveData())
}
But that return :
Promise {
"_U": 0,
"_V": 0,
"_W": null,
"_X": null,
}
Edit : After the answer of Václav Ryska, i can change it with setstate, but that reload once if i call getValue from componentDidMount, and infinite loop in my generaterandomcards function.
My code :
componentDidMount() {
this.getValue()
}
getValue = async () => {
AsyncStorage.getItem('key')
.then(data => {
this.setState({deckDrawToday: true});
})
}
_generateRandomCards() {
console.log(this.state.deckDrawToday)
...
this._generateRandomCardsTrue()
...
return (
this._generateViewCards()
)
}
_generateRandomCardsTrue() {
...
}
_generateViewCards() {
...
}
render() {
return (
this._generateRandomCards()
)
}
return is not a valid statement for async functions, you gotta set the value in a callback to a variable
this.state = {
value: null
}
componentDidMount() {
this.getValue();
}
getValue = async () => {
AsyncStorage.getItem('key')
.then(data => {
this.setState({value: data});
console.log(data)
})
}
use console.log(await this._retrieveData()) since your function is async

React Native async await dispatch store

So I want to make a login feature, in here server will validate first if the username or password is correct or not.
I'm using store, react - redux.
Here is my code when login button pressed
const [statusLogin,setStatusLogin] = useState(null)
let loginInfo = []
function loginButton(){
(async () => {
loginInfo = {username:username,password:password}
const { status } = await dispatch(getUser(loginInfo))
if (status==1){
console.log(status,'in status if 1')
setStatusLogin('granted')
}else{
console.log(status,'in status if else')
setStatusLogin(null)
}
})();
}
Here is my store that suppose to return value 1 or else
if it returned value 1 geb statusLogin will changed as granted
export function getUser(body){
return dispatch =>{
if (!body){
setTimeout(() => {
console.log('no username/pass')
}, 2000);
}else{
setTimeout(() => {
console.log('username/pass validated returning with value 1')
}, 2000);
}
}
}
help me please
This might help
...
function loginButton() {
(async () => {
loginInfo = { username: username, password: password };
await dispatch(getUser(loginInfo, callback));
})();
}
function callback = (status) => {
if (status == 1) {
console.log(status, "in status if 1");
setStatusLogin("granted");
} else {
console.log(status, "in status if else");
setStatusLogin(null);
}
};
reducer.js
export function getUser(body, callback){
return dispatch =>{
if (!body){
setTimeout(() => {
console.log('no username/pass');
callback(0);
}, 2000);
}else{
setTimeout(() => {
console.log('username/pass validated returning with value 1')
callback(1);
}, 2000);
}
}
}
you can use like:
usEffect(( )=>{
if(statusLogin) getUser()
},[statusLogin])
Another thing, your function should not passed callback in. Instead of using callback to change the state, you can use dispatch to modify the reducer.

Using AsyncStorage to show screen on first login

I'm trying to only show the disclosure screen the first time the user logs in by using AsyncStorage. Currently getData is returning a Promise and it goes straight to the landing screen on first login.
Could I get some help to get this functioning the way I want it to?
This is my login handler:
const key = 'key';
const storeData = async () => {
try {
await AsyncStorage.setItem('key', 'true');
} catch (error) {
// saving failed
console.log(error.message);
}
};
const getData = async key => {
let value = '';
try {
value = await AsyncStorage.getItem(key);
return JSON.parse(value);
} catch (e) {
console.log(error.message);
}
};
const _loginHandler = () => {
if (userName == '' || password == '') {
console.log('gagagagagagagagagagagagagagagagag');
} else {
setShowLoading(true);
const payload = {userName: userName.trim(), password: password.trim()};
setUserName('');
setPassword('');
_UserLoginHandler(payload).then(data => {
setShowLoading(false);
if (data.error) {
GlobalShowSnackBar(data.error);
} else {
setTimeout(() => {
setUserId(data);
//props.navigation.replace(getData("key")?'Landing':'Disclosure')
console.log('Key Value ' + JSON.stringify(getData('key'))); <-- this outputs Key Value {"_U":0,"_V":0,"_W":null,"_X":null}
if (getData('key')) {
props.navigation.navigate('Landing');
} else {
storeData(key);
props.navigation.navigate('Disclosure');
}
}, 500);
}
});
}
};
I got it to work with
getData('key').then(val => {
if (val) {
props.navigation.navigate('Landing');
} else {
storeData(key);
props.navigation.navigate('Disclosure');
}
});

Trouble with email validation

This time I have another issue when trying to deal with email validation. When I test my app, I fill the Email TextInput with a valid string, something like Hello#email.com, however, the nonValidInput bool stays at null, and subsequent attempts to post the Email adress don't work either, the nonValidInput bool now it's true when it must be false when entering a correct email adress.
The _onSubmit script is called when the button is pressed.
Here's my code:
state = { username: null, password: null, nonValidInput: null }
_validar = () => {
let email = this.state.username
let pattern = /^(([^<>()\[\]\\.,;:\s#"]+(\.[^<>()\[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
if(pattern.test(String(email).toLowerCase) == true) {
this.setState({ nonValidInput: false })
} else {
this.setState({ nonValidInput: true })
}
console.warn(this.state.nonValidInput)
}
_onSubmit = () =>{
this._validar()
if(this.state.nonValidInput == false) {
const { username, password } = this.state;
} else {
this.setState({ nonValidInput: true })
}
}
Again thank you for your answers.
I found a couple of mistakes in your code.
this.setState is an async process. So call your console.warn() as a callback function.
if (pattern.test(String(this.state.username).toLowerCase()) == true) {
this.setState({ nonValidInput: false }, () => console.warn("true"));
} else {
this.setState({ nonValidInput: true }, () => console.warn("false"));
}
and make _onSubmit function as async until it process _validar function.
_onSubmit = async () => {
await this._validar();
if (this.state.nonValidInput == false) {
const { username, password } = this.state;
} else {
this.setState({ nonValidInput: true });
}
};
toLowerCase is a method, you can't call it as,
pattern.test(String(email).toLowerCase)
Change it to
pattern.test(String(email).toLowerCase())
Finally i see you are duplicating your code. In order to make your code clean add your validation part inside submit.
_onSubmit = () => {
let pattern = /^(([^<>()\[\]\\.,;:\s#"]+(\.[^<>()\[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
if (pattern.test(String(this.state.username).toLowerCase()) == true) {
this.setState({ nonValidInput: false });
// you can call submit
} else {
this.setState({ nonValidInput: true });
// you can handle error
}
};
Hope this helps you. Feel free for doubts.

I am getting `Can not use keyword 'await' outside of a async function` within an Async function.. React-native

I am having an issue with async await for my AsyncStorage function within my React-native application. The error I'm getting is:
Can not use keyword 'await' outside of a async function
As you can see below, it's obvious that await is within the function. What am I doing wrong to get this error?
_retrieveData = async function (location) {
try {
var index = await AsyncStorage.getItem(location, (err, result) => result).then(result => result).catch(error=>console.log(error))
if (index !== null) {
return JSON.parse(index)
}
} catch (error) {
return null
}
};
_storeData = async function(location, value) {
try {
await AsyncStorage.set(location, JSON.stringify(value));
} catch (error) {
console.log(error)
}
};
Use ES6 arrow functions
const _retrieveData = async location => {
try {
let index = await AsyncStorage.getItem(location)
if (index !== null) {
return JSON.parse(index);
}
} catch (error) {
return null;
}
};
const _storeData = async (location, value) => {
try {
await AsyncStorage.set(location, JSON.stringify(value));
} catch (error) {
console.log(error);
}
};
Make them as an arrow functions
_retrieveData = async location => {
try {
let index = await AsyncStorage.getItem(location)
if (index !== null) {
return JSON.parse(index);
}
} catch (error) {
return null;
}
};
_storeData = async (location, value) => {
try {
await AsyncStorage.set(location, JSON.stringify(value));
} catch (error) {
console.log(error);
}
};