У меня проблема с одной частью Firestore. Я пытаюсь отделить все свои запросы данных в отдельные файлы, поэтому мне не нужно повторяться с запросами во внешнем интерфейсе. Поэтому в отдельных файлах я создаю функции, которые принимают параметры и возвращают данные. Пока все хорошо. Когда я использую getDoc(doc(db, 'Projects', 'id) он работает отлично, он возвращает раздел:

const getSection = async (projectID, sectionID) => {
    const docRef = doc(db, `Projects/${projectID}/Sections`, `s${sectionID}`)
    const section = await getDoc(docRef)

    return section.data();
}

Но мой проект требует использования onSnapshot для прослушивания изменений в базе данных и соответствующего изменения внешнего интерфейса. Проблема в том, что я не могу обработать данные, поступающие от слушателя onSnapshot. Я могу регистрировать данные, но не могу сохранить их в переменной, которую могу вернуть. Пример:

const getSection = async (projectID, sectionID) => {
    const docRef = doc(db, `Projects/${projectID}/Sections`, `s${sectionID}`)
    
    let section = {}
    const unsub = onSnapshot(docRef, (doc) => {
        console.log(doc.data());   // This log the exact data that I want

        section = doc.data();
    })
    console.log(section)    // This return undefined

    return section;         // So this returns absolutely nothing
}

**** РЕДАКТИРОВАТЬ ****

Я могу сделать это, когда использую onSnapshot для доступа к коллекциям:

    const getAllSections = async (sectionID, projectID) => {
        let sections = [];
        const sectionCollectionRef = collection(db, `Projects/${projectID}/Sections`)

        onSnapshot(sectionCollectionRef, (snap) => {
            snap.forEach((section) => {
                sections.push(section.data())
            })
        })
        console.log(sections) // This works perfectly and every time something changes it refreshes the frontend
    
    return sections;
}

Вот что я пытаюсь сделать, получая информацию из документа, а не из коллекции.

0
VeniM 4 Окт 2022 в 21:37
1
Смысл onSnapshot в том, чтобы получить несколько значений, распределенных во времени. Что вы хотите вернуть, только первое значение?
 – 
Nicholas Tower
4 Окт 2022 в 21:44
Я хочу сохранять/обновлять значение каждый раз при обновлении базы данных, чтобы обновлять внешний интерфейс.
 – 
VeniM
5 Окт 2022 в 01:15
Используете ли вы интерфейсный фреймворк или просто JavaScript?
 – 
samthecodingman
5 Окт 2022 в 01:50
Я использую React
 – 
VeniM
5 Окт 2022 в 01:59

2 ответа

Данные загружаются из Cloud Firestore асинхронно. Поскольку это может занять некоторое время, код после обратного вызова сразу же продолжается. Затем, когда данные доступны, Firestore вызывает обратный вызов onSnapshot.

Поэтому весь код, которому требуется доступ к данным, должен находиться внутри обратного вызова onSnapshot.

0
Mark Munene 4 Окт 2022 в 21:52

Поскольку вы говорите, что используете реакцию, это должно быть сделано в useEffect, и вы должны устанавливать состояние каждый раз, когда поступают новые данные.

const SomeComponent = () => {
  const [section, setSection] = useState();
  useEffect(() => {
    const docRef = doc(db, `Projects/${projectID}/Sections`, `s${sectionID}`)
    
    const unsub = onSnapshot(docRef, (doc) => {
      setSection(doc.data();
    })
    return unsub
  }, [sectionId]);

  // ... rest of the component which uses `section`
}
0
Nicholas Tower 5 Окт 2022 в 02:55
Это работает, но я пытаюсь разделить эти запросы к базе данных в отдельный файл, чтобы не писать один и тот же код во всех компонентах, которым он нужен. Это сложно поддерживать таким образом, и если из firestore придет обновление, которое сломает код, мне нужно будет зайти в каждый компонент и исправить его по отдельности.
 – 
VeniM
5 Окт 2022 в 03:14