Почему государство всегда пусто? - PullRequest
0 голосов
/ 15 апреля 2020

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

Вот мой код:

const UsersScreen = (props) => {

    const [state, setState] = useState({
        users: []
    });  

    const getUserProfiles = () => {
        let users = [];
        //networkUsers is an array with the ids
        networkUsers.forEach(userId => { 
            db.doc(userId).get().then((doc) => {
                users.push(doc.data());
                console.log('localusers', users)
            }).catch((error) => {
                console.log('caught error', error)
            })
        });

        setState({ users: users });
    };


    useEffect(() => {
        getUserProfiles();
    }, []);

console.log('state', state.users)
}

Пожалуйста, помогите.

1 Ответ

4 голосов
/ 15 апреля 2020

Лог c, извлекающий документ из Firestore, является асинхронным. Однако вызов setState является синхронным. Всегда будет до документа, выбранного. Решением было бы получить документы , а затем установить состояние. Вот пример:

const UsersScreen = (props) => {
  const [state, setState] = useState({
    users: [],
  });

  const getUserProfiles = () => {
    Promise.all(networkUsers.map((userID) => db.doc(userId).get()))
      .then((docs) => {
        setState({ users: docs.map((doc) => doc.data()) });
      })
      .catch((err) => {
        console.log("caught error", error);
      });
  };

  useEffect(() => {
    getUserProfiles();
  }, []);

  console.log("state", state.users);
};

Вызов Promise.all разрешается, как только каждый пользователь был извлечен из Firestore (хотя, возможно, вы могли бы получить их сразу же). Как только у нас есть пользователи, мы l oop над ними с map, чтобы извлечь данные документа и установить состояние. Вот альтернатива с async/await:

const UsersScreen = (props) => {
  const [state, setState] = useState({
    users: [],
  });

  const getUserProfiles = async () => {
    try {
      const docs = await Promise.all(
        networkUsers.map((userID) => db.doc(userId).get())
      );

      setState({ users: docs.map((doc) => doc.data()) });
    } catch (err) {
      console.log("caught error", error);
    }
  };

  useEffect(() => {
    getUserProfiles();
  }, []);

  console.log("state", state.users);
};
...