Почему моя собственная реагирующая функция всегда возвращает undefined? - PullRequest
0 голосов
/ 19 мая 2019

Я использую реагирующий натив, и я только что перенес некоторые функции базы данных в отдельный файл, вместо того, чтобы просто поместить их в нужные мне файлы (я начал использовать одни и те же функции в нескольких файлах, и я 'Я предпочел бы иметь их всех в одном месте).Проблема в том, что функция, которая должна сравнивать одноразовый ключ с ключом в базе данных, всегда возвращает undefined .

Я пытался вернуть функции вместо логических значений и пыталсяиспользуйте ключевые слова "async / await" (о которых я очень мало знаю).

Вот мой код ...

/ 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);

Всякий раз, когда я ставлю инструкцию возврата после функция firebase "Once" возвращает логическое значение, но по какой-то причине оно всегда ложно.Любая помощь с благодарностью!

Ответы [ 3 ]

1 голос
/ 19 мая 2019

Обращаясь к этому: Всякий раз, когда я помещаю инструкцию возврата после функции «один раз» в firebase, она возвращает логическое значение, но по какой-то причине оно всегда ложно.

Удалив код метода .once(), вы сможете ясно понять, почему это так. Код выполняется точно так, как если бы он был написан, как показано ниже. Из-за асинхронного характера метода .once() оператор return выполняется до разрешения (завершения) .once().

isValidCode(text) {
  let codeIsFound = false;
  let identifier = "";
  // .once() goes here
  return codeIsFound;
};

Ваш инстинкт был хорошим в асинхронности / ожидании. Чтобы исправить вашу проблему, сделайте это:

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; 
};

Затем функция вернет обещание, которое будет разрешено (или отклонено). Поэтому для использования этого кода выполните:

isValidCode('something').then(result => {
   /* use result here */
};
0 голосов
/ 19 мая 2019

Как и у @randy casburn, проблема та же. Просто изменив решение, данное @ randy.

    async isValidCode(text) { let codeIsFound = false; let identifier = ""; if(await this.codesRef.once function call ) {
Return true;
} else {return false;} };
0 голосов
/ 19 мая 2019

once() возвращает Promise<DataSnapshot>, что означает, что оно асинхронное, и вы не можете вернуть значение из асинхронного метода.

Чтобы решить вашу проблему, вы можете сделать следующее:

    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;
          takeValue(codeIsFound);
        }
      });
    });
};

takeValue(value){
 console.log(value) //true
}

Здесь вы создаете новый метод внутри once(), а затем добавляете значение в качестве аргумента.

...