Консультируйтесь с Firebase в каждом цикле карты массива

У меня есть массив, и я запускаю его с картой для рендеринга некоторых компонентов

const list = [{'id':1,'name':'a'},{'id':2,'name':'b'},{'id':3,'name':'c'}]

list.map(item=>{
  return <Item key={item.id}/>
})

Это прекрасно работает для меня. Но теперь мне нужно сделать запрос в firebase в каждом цикле карты и отправить результат этого запроса

list.map(item=>{

  let firebasedata=[]
  var ref = database.ref('example');
  //acá hago la consulta a Firebase por cada cíclo del map, me devuelve un array y lo guardo en firebasedata para enviarlo como props en cada <Item/>

  ref.orderByChild('id').equalTo(item.id).on('value', snapshot => {
    snapshot.forEach(x=> {
      firebasedata.push(x.val())
    }); 
    console.log(firebasedata) //acá me muestra cada array de cada consulta en los ciclos
  });

  console.log(firebasedata) //pero acá sólo obtengo arrays vacíos, y al momento de enviarlo como props en el return del <Item/> también llega vacío el array

  return <Item key={item.id}  firebasedata={firebasedata}/>  //firebasedata está vacío por cada <Item/>
})

Как я могу выполнить запрос на каждой итерации карты и отправить этот ответ каждому как реквизит?

0
задан 01.12.2019, 18:55
1 ответ

Простой способ это делать serГ - в посредством RxJs. Firebase поставляет одну librerГ - чтобы для использовать RxJs с Firebase, названным rxfire . Эта librerГ - позволяет тебе получать документы и обращать их в Наблюдаемые , так что ты можешь преобразовывать документы в твой вкус.

import React, { useEffect, useState } from 'react'
import { doc } from 'rxfire/database'
import { of } from 'rxjs'
import { map, mergeMap } from 'rxjs/operators'
import { database } from '../../utils/firebase'

const UsersList = ({ rawList }) => {
  const [users, setUsers] = useState([])

  useEffect(() => {
    const usersRef = database.ref('example').orderByChild('id')
    // creamos un observable a partir de la lista
    of(rawList)
      // la transformamos para obtener solos los ids
      .pipe(map(item => item.id))
      // volvemos a transformar la lista
      .pipe(
        // iteramos los ids y usamos cada id para encontrar al documento
        // y devolver el observable con su data (el array de c/snapshot)
        mergeMap(id => (
          doc(usersRef.equalTo(id))
            .pipe(
              map(snapshot => snapshot.val())
            )
        ))
      )
      // por último nos subscribimos para obtener los
      // datos planos (ya no observables)
      .subscribe(users => setUsers(users))
  })

  return (
    <ul>
    { users.map(user => (
        <li>{user.name}</li>
      ))
    }
    </ul>
  )
}

Другая opciГіn состоит в том, чтобы повторять список посредством одного for of, искать документ и сохранять это в обещании; так что у тебя был array обещаний.

const usersPromises = []
for (const item of list) {
  usersPromises.push(
    new Promise((resolve) => {
      usersRef
       .orderByChild('id')
       .equalTo(item.id)
       .on('value', snapshot => {
         resolve(...(snapshot.map(s => s.val()))
       })
}
Promise
  .all(usersPromises)
  .then(users => setUsers(users)
1
ответ дан 01.12.2019, 22:14

Теги

Похожие вопросы