简体   繁体   English

返回清理 function 从异步 function 中的 userEffect 中返回 react Native

[英]return a cleanup function returning form the async function in userEffect in react Native

I am using a firebase onSnapshot method to use realtime data in react native app and wrote a separate async function to listen to the firestore as given below,我正在使用 firebase onSnapshot 方法在反应原生应用程序中使用实时数据,并编写了一个单独的异步 function 来收听 Firestore,如下所示,

async function getData() {

    let collName = await AsyncStorage.getItem('@collection_name')
    let subscriber = shopReference.collection(collName).onSnapshot((snap) => {
        let menuList = [];
        snap.forEach((doc) => {
          menuList.push({
            id: doc.id,
            ...doc.data(),
          });
        });
    
        setMenu(menuList);
      });

      return subscriber;
}

I am using useEffect to call this function and I want to return the subscriber method returning from the firestore as a cleanup function.我正在使用 useEffect 调用此 function 并且我想返回从 Firestore 返回的订阅者方法作为清理 function。 I know that I can achieve that by directly implement this code inside the useEffect function.我知道我可以通过在 useEffect function 中直接实现此代码来实现这一点。 But since I am using AsyncStorage to retrieve a collection id I need to put it inside async function.但由于我使用 AsyncStorage 来检索集合 id,我需要将它放在异步 function 中。 I can't return the response of the getData() method since it returns promise instead of subscriber function.我无法返回getData()方法的响应,因为它返回 promise 而不是订阅者 function。 What is the best solution to resolve this issue?解决此问题的最佳解决方案是什么?

EDIT编辑

I tried all the following methods to call the function inside the useEffect function.我尝试了以下所有方法来调用useEffect function内部的function。

// Without returning anything, but according to the firestore doc. This may cause data leaks.
useEffect(() => {
        getData();
      }, []);

// directly returning the method, this cause error that promise cant be accepted as a clean up function.
useEffect(() => {
        return getData();
      }, []);



useEffect(() => {
        getData().then((subscriber) => {
             return () => subscriber();
        });
      }, []);

You cannot change getData to immediately return a cleanup function.您不能更改getData以立即返回清理 function。 You'd rather use你宁愿用

useEffect(() => {
    let subscriber = () => {};
    getData().then(sub => {
         subscriber = sub;
    });
    return () => {
         subscriber();
    };
}, []);

or或者

useEffect(() => {
    const subscriberPromise = getData();
    return async () => {
         const subscriber = await subscriberPromise;
         subscriber();
    };
}, []);

However, these are not ideal when the cleanup function gets called before the promise was fulfilled (not to mention error handling…).然而,当清理 function 在 promise 完成之前被调用时,这些并不理想(更不用说错误处理......)。 While the first doesn't work at all in that case, the second still unnecessarily starts the subscription.虽然在这种情况下第一个根本不起作用,但第二个仍然不必要地启动订阅。 To do it properly, I'd suggest something like为了正确地做到这一点,我建议像

useEffect(() => {
    let cleanup = () => {};
    AsyncStorage.getItem('@collection_name').then(collName => {
        if (!cleanup) return; // already cancelled
//      ^^^^^^^^^^^^^^^^^^^^
        cleanup = shopReference.collection(collName).onSnapshot((snap) => {
            let menuList = [];
            snap.forEach((doc) => {
                menuList.push({
                    id: doc.id,
                    ...doc.data(),
                });
            });
            setMenu(menuList);
        });
    });

    return () => {
         cleanup();
         cleanup = null;
    };
}, []);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM