Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
75 views
in Technique[技术] by (71.8m points)

javascript - Matching properties of objects in two different arrays

Background

I'm building a "Liked Stores" screen for an app I'm developing. This screen renders a flatlist which shows cards with each store a user has liked. The way I'm handling the process is that when a user likes a store, it creates a new doc in firestore which holds the id of the store and a "liked" boolean.

Problem

I've been trying to filter the totality of stores in my db and match the id's of the liked stores with the id's in the "liked" collection documents.

The data structure is:

user/uid/favorites, each doc here contains 2 fields. An id (matching to another id in the stores/ collection) and a boolean indicating that it has been liked. And then stores/'s docs contain lots of data but what matters here is a field which holds an id.

I've tried implementing the following solution, with two subscribers bringing each collection and a function which handles the filtering. But for some reason I don't quite understand I just can't get it to work.

Code is as follows:

const [stores, setStores] = useState([]);
     useEffect(() => {
        const subscriber = firebase.firestore()
        .collection('stores/')
        .onSnapshot(querySnapshot => {
          const stores = [];
    
          querySnapshot.forEach(documentSnapshot => {
            stores.push({
              ...documentSnapshot.data(),
              key: documentSnapshot.id,
            });
          });
    
          setStores(stores);
        });
    
      return () => subscriber();
    }, [])

    const [liked, setLiked] = useState([]);

    useEffect(() => {
        const subscriber = firebase.firestore()
        .collection('users/' + userId + '/favorites')
        .onSnapshot(querySnapshot => {
          const liked = [];
    
          querySnapshot.forEach(documentSnapshot => {
            liked.push({
              ...documentSnapshot.data(),
              key: documentSnapshot.id,
            });
          });
    
          setLiked(liked);
        });
    
      return () => subscriber();
    }, [])
    
    const usefulData = [];
      const handleFilter = (obj) => {
       for(let i = 0; i < stores.length; i++){
        if(obj.id === liked[i].storeId) {
            usefulData.push(obj)
        }
       }
    }
        stores.filter(handleFilter);

And then I'm passing usefulData as the data param to the FlatList.

When printing usefulData it simply returns an empty array.

Question

Can anyone provide a solution and an explanation as to why this is not working and how to compare two arrays of objects' values properly?

question from:https://stackoverflow.com/questions/65928568/matching-properties-of-objects-in-two-different-arrays

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Well, figured it out in the most uncomfortable and least elegant possible way so any tips or better ideas will still be fondly accepted:

const likedIds = [];
    liked.forEach(o => likedIds.push(o.id));
    const storeIds = [];
    stores.forEach(o => storeIds.push(o.id));
    
    const intersection = storeIds.filter(element => likedIds.includes(element));

    const [data, setData] = useState([]);
    const finalArray = [];
    useEffect(() => {
    for (let i = 0; i < intersection.length; i++){
      const fetchQuery = async () => {
        
        const storeData = await firebase.firestore()
        .collection('stores/')
        .doc(intersection[i])
        .get()
        .then(documentSnapshot => {
          if (documentSnapshot.exists) {
            finalArray.push(documentSnapshot.data())

          }
        });
        setData(finalArray)
      }
      fetchQuery()
      
    }
  
    }, [])

Without changing anything else from what is posed in the question, this is what I added in order to get this working. First I get all the Id's out of each array of objects, then filter them and store them in a new array. Then we can go ahead and build a new array of objects using a handy fetchQuery async function to get all the data from the original stores collection, just that this time it only brings up the stores with ids in the intersection array.

I am perfectly aware that this is the most bodged out and disgusting possible solution, but at the very least it works. Hope someone smarter than me can get some help out of this and make my solution much better!


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...