Массив setState и получить массив React Native - PullRequest
0 голосов
/ 18 октября 2018

Я пытаюсь установить массив в состояние, но, похоже, он не устанавливается.Я разместил часть своего кода ниже.

Что я хочу сделать, так это то, что пользователь может загрузить элемент в основную коллекцию на firestore, затем этот элемент будет показан в главном списке на главномэкран.

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

Я применил подход, согласно которому элемент загружается в основную коллекцию в firestore, а затем идентификатор документа и ссылка на коллекцию, т. Е. «C» оба помещаются в документ в под-коллекции под названием userItems снаходится в документе этого конкретного пользователя.Я думаю, что это лучший способ сделать это, поэтому у меня есть только «1 источник правды» и мне не нужно беспокоиться о дубликатах, особенно если мне придется обновлять какие-либо документы в будущем.

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

Спасибо за любую помощь :)

UserProfile.js

constructor() {
    super();

    this.getUserItems = this.getUserItems.bind(this);


    this.state = {
        Name: '',
        Location: '',
        items: [],
        Keys: [],
        test: ''
    };
}

componentDidMount() {
    console.log('UserProfile');

    this.getUserItems();
    //this.queryKeys();

}


getUserItems = () => {

    const Keys = [];

    const userCollectionRef = firebase.firestore()
        .collection('a').doc('b')
        .collection('c')




    userCollectionRef.get()
        .then((querySnapshot) => {
            console.log("user doc received");

            querySnapshot.forEach(function (doc) {

                console.log('Doc.id: ', doc.id);
                console.log('Doc.Key: ', doc.data().Key);
                console.log('Doc.CollectionRef: ', doc.data().CollectionRef);

                const {Key, CollectionRef} = doc.data();

                Keys.push({
                    Key,
                    CollectionRef
                })

            }); // foreach loop end
this.queryKeys(keys);




        }).catch(function (error) {
        console.error("getUserItems => error: ", error);
    });

  //  this.setState(() =>({
    //    Keys,
      //  test: 'testString'
   // }));

    console.log("Keys inside: ", Keys);
};


queryKeys(keys) {
    const items = [];


    console.log("queryKeys Called!");
    console.log("queryKeys :", keys);
    console.log('test: ', this.test);



    keys.forEach(function(Key, CollectionRef)  {

        console.log("Key array: ", Key);
        console.log("CollectionRef array: ", CollectionRef);

        firebase.firestore
            .collection('a').doc('b')
            .collection(CollectionRef)
            .doc(Key)
            .get().then(function (doc) {

            console.log("doc received");

            const {Name, imageDownloadUrl, Location} = doc.data();

            items.push({
                key: doc.id,
                doc, // DocumentSnapshot
                Name,
                imageDownloadUrl,
                Location,
            });

        }).catch(function (error) {
            console.error("queryKeys: error: ", error);
        })

    }) // forEach end

    this.setState({
        items
    });

}

ОБНОВЛЕНИЕ:

Я решил использовать другой подход, где я просто называю queryKeysФункция в конце .then в getUserItems и просто передает ключи в качестве параметра.этот способ работает, поскольку он получает массив в нужное время, но теперь я получаю сообщение об ошибке из firestore: firestore error

, когда я делаю это:

firebase.firestore
        .collection('a').doc('b')
        .collection('c')
        .doc('docID').get()
        .then((doc) => {

Как я могу получить документ по идентификатору?

Спасибо

1 Ответ

0 голосов
/ 18 октября 2018

Модификации, которые я сделал ниже, очень грязные, я подозреваю, что ваша проблема заключается в том, что вы вызываете setState в обоих ваших методах выше, прежде чем ваш цикл будет выполнен.

Вы выполняете цикл синхронно, выполняете асинхронное действие внутри цикла, выходите из цикла (синхронно) и вызываете setState, ожидая, что массивы будут заполнены данными, извлеченными внутри цикла, этого не произойдет, поскольку вы не ожидаете AJAX-запросов на запуск базы.

То, что я сделал ниже, это поместил вызовы setState внутри разрешения обещания в каждом из ваших циклов, это не идеально (на самом деле это ужасная идея для производства), так как это будетобновлять состояние для каждого элемента в списке, а не после сбора всех данных.Вы должны сделать этот цикл, есть много способов сделать это.Это должно продемонстрировать смысл, и вы должны увидеть данные на экране.

constructor() {
    super();

    this.getUserItems = this.getUserItems.bind(this);


    this.state = {
        Name: '',
        Location: '',
        items: [],
        Keys: [],
        test: ''
    };
}

componentDidMount() {
    console.log('UserProfile');

    this.getUserItems();
    this.queryKeys();

}


getUserItems = () => {

    const Keys = [];

    const userCollectionRef = firebase.firestore()
        .collection('a').doc('b')
        .collection('c')




    userCollectionRef.get()
        .then((querySnapshot) => {
            console.log("user doc received");

            querySnapshot.forEach(function (doc) {

                console.log('Doc.id: ', doc.id);
                console.log('Doc.Key: ', doc.data().Key);
                console.log('Doc.CollectionRef: ', doc.data().CollectionRef);

                const {Key, CollectionRef} = doc.data();

                Keys.push({
                    Key,
                    CollectionRef
                })


            });

              this.setState(() =>({
                    Keys,
                    test: 'testString'
                }));

        }).catch(function (error) {
        console.error("getUserItems => error: ", error);
    });



    console.log("Keys inside: ", Keys);
};


queryKeys() {
    const items = [];


    console.log("queryKeys Called!");
    console.log("queryKeys :", this.state.Keys);
    console.log('test: ', this.test);



    this.state.Keys.forEach(function(Key, CollectionRef)  {

        console.log("Key array: ", Key);
        console.log("CollectionRef array: ", CollectionRef);

        firebase.firestore
            .collection('a').doc('b')
            .collection(CollectionRef)
            .doc(Key)
            .get().then(function (doc) {

            console.log("doc received");

            const {Name, imageDownloadUrl, Location} = doc.data();

            items.push({
                key: doc.id,
                doc, // DocumentSnapshot
                Name,
                imageDownloadUrl,
                Location,
            });

         this.setState({
             items
         });

        }).catch(function (error) {
            console.error("queryKeys: error: ", error);
        })

    }) // forEach end



}

Ниже вы увидите грубый пример того, как вы можете сделать цикл асинхронным, используя async & await, неуверенный, если Firebase API хорошо с этим справится, вам, вероятно, придется немного почитатьих документы.

queryKeys() {
    const items = [];


    console.log("queryKeys Called!");
    console.log("queryKeys :", this.state.Keys);
    console.log('test: ', this.test);



    this.state.Keys.forEach(async function(Key, CollectionRef)  {

        console.log("Key array: ", Key);
        console.log("CollectionRef array: ", CollectionRef);

        try {
            let result = await firebase.firestore
            .collection('a').doc('b')
            .collection(CollectionRef)
            .doc(Key)
            .get();


            const {Name, imageDownloadUrl, Location} = result.data();

            items.push({
                key: doc.id,
                doc, // DocumentSnapshot
                Name,
                imageDownloadUrl,
                Location,
            });
        } catch (e) {
            console.error("queryKeys: error: ", error);
        }
    }) // forEach end


    this.setState({
        items
    })

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...