У меня есть массив, и я запускаю его с картой для рендеринга некоторых компонентов
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/>
})
Как я могу выполнить запрос на каждой итерации карты и отправить этот ответ каждому как реквизит?
Простой способ это делать 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)