Why Does My React Native Function Always Return Undefined?
I am using react native and I have just migrated some database functions to a individual file, instead of just having them in the files where I need them (I have started needing to use the same functions in multiple files, and I'd rather have them all in one place). The problem is, the function that is supposed to compare a one time key with one in the database, always returns undefined.
I have tried returning functions instead of booleans, and have attempted to use "async/await" keywords (which I know very little about).
Here is my code...
/project/src/components/Database.js
var firebase = require('firebase');
if (!firebase.apps.length) {
firebase.initializeApp({
apiKey: "key",
authDomain: "domain",
databaseURL: "url",
storageBucket: "bucket",
});
}
class Database {
constructor() {
this.codesRef = firebase.database().ref('codes');
}
isValidCode(text) {
let codeIsFound = false;
let identifier = "";
this.codesRef.once('value', (db_snapshot) => {
db_snapshot.forEach((code_snapshot) => {
//console.log(text, code_snapshot.val().value, text == code_snapshot.val().value);
if (text == code_snapshot.val().value) {
codeIsFound = true;
identifier = code_snapshot.key;
}
});
//console.log(codeIsFound); // this is correct
return codeIsFound; // this always returns undefined
});
};
}
module.exports = Database;
/project/src/components/forms/KeyForm.js
import React from 'react';
import {
StyleSheet,
View,
TextInput,
} from 'react-native';
import { withNavigation } from 'react-navigation';
import database from '../Database.js';
const db = new database();
class LoginForm extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<View style={styles.container}>
<TextInput
style={styles.input}
placeholder="Access Code"
returnKeyType="go"
onSubmitEditing={text => {console.log(db.validCode(text.nativeEvent.text))}} // "undefined"
autoCapitalize="none"
autoCorrect={false}
/>
</View>
);
}
}
const styles = StyleSheet.create({\
// yay styles :)
});
export default withNavigation(LoginForm);
Whenever I put a return statement after the firebase "once" function, it does return a boolean, but for some reason it is always false. Any help is greatly appreciated!
Answer
Addressing this: Whenever I put a return statement after the firebase "once" function, it does return a boolean, but for some reason it is always false.
By removing the .once()
method code, you can clearly see why this is the case. The code executes exactly as if it were written like below. Due to the async nature of the .once()
method, the return
statement executes prior to the .once()
resolving (completing).
isValidCode(text) {
let codeIsFound = false;
let identifier = "";
// .once() goes here
return codeIsFound;
};
Your instinct was a good one about async/await. To fix your issue, do this:
async isValidCode(text) {
let codeIsFound = false;
let identifier = "";
let db_snapshot = await this.codesRef.once('value');
db_snapshot.forEach(code_snapshot => {
if (text == code_snapshot.val().value) {
codeIsFound = true;
identifier = code_snapshot.key;
}
});
return codeIsFound;
};
Then, the function will return a promise that will be resolved (or rejected). So to use this code do:
isValidCode('something').then(result => {
/* use result here */
};
Related Questions
- → How to update data attribute on Ajax complete
- → October CMS - Radio Button Ajax Click Twice in a Row Causes Content to disappear
- → Octobercms Component Unique id (Twig & Javascript)
- → Passing a JS var from AJAX response to Twig
- → Laravel {!! Form::open() !!} doesn't work within AngularJS
- → DropzoneJS & Laravel - Output form validation errors
- → Import statement and Babel
- → Uncaught TypeError: Cannot read property '__SECRET_DOM_DO_NOT_USE_OR_YOU_WILL_BE_FIRED' of undefined
- → React-router: Passing props to children
- → ListView.DataSource looping data for React Native
- → Can't test submit handler in React component
- → React + Flux - How to avoid global variable
- → Webpack, React & Babel, not rendering DOM