Невозможно сохранить значение поля из хранилища данных в переменную

Я пытаюсь сохранить значение поля имя, прочитанное из документа в хранилище пользователей, в переменную userName, чтобы я мог изменить значение состояния userName. В общем, как я могу сохранить значение поля в переменной и сохранить его в моем компоненте? Всегда ценю помощь каждого.

export default class Main extends Component {
state = {
    currentUser: null,
    userName: null
  };

getName = async () => {
    const { currentUser } = firebase.auth();
    this.setState({ currentUser });
    const uid = currentUser.uid;
    let userName = null;
    let docRef = await db.collection("users").doc(uid);
    docRef.get().then(doc => {
      userName = doc.data().name;
      console.log(userName);
      // this prints out "panda"
    });
    console.log(userName);
    // this prints out null
    this.setState({ userName });
  };

  componentWillMount() {
    this.getName();
  }

введите описание изображения здесь


person Grace Kim    schedule 28.12.2019    source источник


Ответы (1)


Нижний console.log(userName) печатает null, потому что ваш await установлен в назначении документа ref, а не в .get(). .doc() возвращает ссылку, а .get() возвращает обещание.

Это приводит к тому, что ваш код не ожидает обещания, возвращенного .get(), и при перемещении проходит весь этот блок, тем самым показывая значение null для userName, поскольку обещание еще не было разрешено. Есть несколько способов сделать это. Один из способов - поместить ваш setState() внутри блока .then(), как в следующем примере:

Измените свой getName() на это:

getName = async () => {
    const { currentUser } = firebase.auth();
    this.setState({ currentUser });
    const uid = currentUser.uid;
    await db
        .collection("users")
        .doc(uid)
        .get()
        .then(doc => {
            if (doc && doc.exists) {
                this.setState({ userName: doc.data().name });
            }
        });
};

Я оставил там async/await на тот случай, если вы добавите в этот метод дополнительную логику, которая потребует ожидания запроса firebase. В противном случае вы можете удалить как async, так и await.

person Michael Rodriguez    schedule 28.12.2019
comment
Спасибо, то, что вы предложили, сработало. Просто из любопытства я удалил async и await и присвоил имя doc.data (). Локальной переменной, созданной перед оператором запроса, но она все еще оставалась нулевой. Вы можете объяснить, почему это произошло? - person Grace Kim; 28.12.2019
comment
если вы хотите установить переменную вне области видимости блока .then(), вам нужно будет сохранить async / await, так как вам нужно будет дождаться разрешения обещания, прежде чем переходить к остальной части кода. Если этот ответ был полезен, подумайте о том, чтобы установить его как принятый ответ :) - person Michael Rodriguez; 28.12.2019