Не може да се съхрани стойност на поле от firestore в променлива

Опитвам се да съхраня стойността на полето name, прочетена от документ във firestore users в променлива 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) отпечатва нула, защото вашият await е зададен на присвояването на референтния документ, а не на .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().name на локалната променлива, инстанцирана преди заявката за заявка, но тя все още остана като null. Можете ли да обясните защо това би се случило? - person Grace Kim; 28.12.2019
comment
ако искате да зададете променливата извън обхвата на блока .then(), тогава ще трябва да запазите async/await, тъй като ще трябва да изчакате обещанието да се разреши, преди да продължите с останалата част от кода. Ако този отговор е бил полезен, моля, помислете дали да не го зададете като приет отговор :) - person Michael Rodriguez; 28.12.2019