Tengo una colección de publicaciones en Firestore de la que obtengo todas las publicaciones creadas por los usuarios en una lista [usuario1, usuario2, ...]. Puedo escuchar los cambios en la colección usando onSnapshot en el siguiente método:
export default function Feed({ friendList }) { // currentUser context const { currentUser } = useAuth(); // array to save posts from database const [posts, setPosts] = useState([]); // function to fetch data from database useEffect(() => { db.collection('posts') .where('userId', 'in', [...friendList]) .orderBy('timestamp', 'desc') .onSnapshot((snapshot) => { setPosts( snapshot.docs.map((doc) => ({ id: doc.id, post: doc.data(), })) ); }); }, []); return ( <div className='feed'> {currentUser ? ( <div className='feed_container'> {posts.map(({ id, post }) => { return ( <Post key={id} id={id} userProfileURL={post.userProfileURL} username={post.username} displayName={post.displayName} photoURL={post.photoURL} /> ); })} </div>Pero esta consulta 'en' no funcionará si la lista de amigos tiene más de 10 elementos. Entonces puedo obtener los documentos requeridos de la colección usando promesas como:
useEffect(() => { getPostsFromFriendsList(friendList); }, []); async function getPostsFromFriendsList(friendList){ const promises = []; for (let i = 0; i < friendList.length; i++) { promises.push(getPosts(friendList[i])); } const postsForHomeFeed = await Promise.all(promises); const array = []; for (let i = 0; i < postsForHomeFeed.length; i++) { postsForHomeFeed[i].docs.map((doc) => { array.push({ id: doc.id, post: doc.data(), }); }); } setPosts(array); } function getPosts(userId) { return new Promise((resolve, reject) => { db.collection('posts') .where('userId', 'in', [userId]) .onSnapshot((snapshot) => { resolve(snapshot); }); }); }Pero ya no puedo escuchar los cambios en la base de datos para actualizar mi estado de reacción para representar en consecuencia si se agregó o eliminó una publicación en mi colección de Firestore. ¿Cómo puedo configurar mi useEffect para la solución de promesas en el segundo código de modo que pueda actualizar mi estado de reacción cada vez que haya un cambio en la colección de firestore? Gracias.
Debería dejar los oyentes abiertos y actualizar el estado cada vez que se activan y fusionar los datos de acuerdo con las id de publicación como aquí:
useEffect(() => { getPostsFromFriendsList(friendList); }, []); //source: https://stackoverflow.com/questions/7146217/merge-2-arrays-of-objects const merge = (a, b, prop) => { var reduced = a.filter( (aitem) => !b.find((bitem) => aitem[prop] === bitem[prop]) ); return reduced.concat(b); }; async function getPostsFromFriendsList(friendList) { const promises = []; for (let i = 0; i < friendList.length; i++) { db.collection("posts") .where("userId", "in", [friendList[i]]) .onSnapshot((snapshot) => { const array = []; snapshot.docs.map((doc) => { array.push({ id: doc.id, post: doc.data(), }); }); setPosts(merge([...posts], array, "id")); }); } }Use el bloque onSnapshot en useEffect . Ejemplo sencillo;
useEffect(() => { onSnapshot(collection(db, "profiles"), (snapshot) => { setProfiles(snapshot.docs.map((doc)=>({...doc.data(), id: doc.id}))) }) console.log(profiles); }); El estado de los profiles contendrá elementos actualizados todo el tiempo.