【问题标题】:React Native memory leak error after updating to Firebase version 9 onValue更新到 Firebase 版本 9 onValue 后 React Native 内存泄漏错误
【发布时间】:2022-02-17 09:49:56
【问题描述】:

我将更新 Firebase 版本 9 模块化表单的代码。我现在正在使用 onValue。从我正在阅读的内容中,它返回一个删除侦听器的函数。但我仍然没有做对,因为虽然它一开始运行良好,但当我在打开应用程序的情况下更改后端数据库时,我得到“无法对未安装的组件执行反应状态更新”错误。 m 在不同的应用程序屏幕中。请参阅下面的旧代码和新代码。

旧代码:

useEffect(() => {
  loadListings();
},[]);

const loadListings = async () => {  
  setLoading(true);
  updateInput('');
  let testData = [];
  let searchData = [];
  db.ref('deals').once('value', (snapshot) =>{
    snapshot.forEach((child)=>{
      testData.push({
        id: child.key,
        title: child.val().hasOwnProperty('title') ? child.val().title : 'NA',
      })
      searchData.push(
        child.val().title
      )
    }) 
  })
  .then(()=>{
    checkMessages(testData);
    setLoading(false);
  })
  .catch((error) => Sentry.Native.captureException('Error MessagesScreen function loadListings 1 ' + error));
}

新代码:

useEffect(() => {
    loadListings();
  },[]);

const loadListings = async () => {  
  setLoading(true);
  updateInput(''); 
  const dbRef = ref(db, 'deals');
  return onValue(dbRef , (snapshot) => {
    let testData = [];
    let searchData = [];
    let storeData = filterStores;
    snapshot.forEach((childSnapshot)=>{
      testData.push({
        id: childSnapshot.key,
        title: childSnapshot.val().hasOwnProperty('title') ? childSnapshot.val().title : 'NA',
      })
    }) 
    checkMessages(testData);
    setLoading(false);
  })
} 

在收到下面的答案后,我将 useEffect 更改为这个,现在它可以工作了:

  useFocusEffect(
    React.useCallback( () => {
      async function fetchData() {
        // You can await here
        const response = await loadListings();
        // ...
        return () => response();
      }
      fetchData();
    }, [])
  );

【问题讨论】:

    标签: javascript react-native firebase-realtime-database


    【解决方案1】:

    你提到了unsubscribe function returned from onValue。为了调用它,我认为您需要从调用中获取它,然后在某些导航状态更改时调用它。

    假设您使用的是 React Navigation,它可能看起来像这样(使用 useFocusEffect

    import { useFocusEffect } from '@react-navigation/native';
    
    function YourComponent() {
      const [loading, setLoading] = React.useState(false)
    
      useFocusEffect(
        React.useCallback(async () => {
          const unsubscribe = await loadListings();
    
          return () => unsubscribe();
        }, [])
      );
    
      const loadListings = async () => {  
        setLoading(true);
        updateInput(''); 
        const dbRef = ref(db, 'deals');
        return onValue(dbRef , (snapshot) => {
          let testData = [];
          let searchData = [];
          let storeData = filterStores;
          snapshot.forEach((childSnapshot)=>{
            testData.push({
              id: childSnapshot.key,
              title: childSnapshot.val().hasOwnProperty('title') ? childSnapshot.val().title : 'NA',
            })
          }) 
          checkMessages(testData);
          setLoading(false);
        })
      } 
    
      return <View />;
    }
    

    也不要忘记将async/await 用于您的异步loadListings 函数,或者使用.then()。否则,您将面临一个未解决的承诺。

    我还找到了一个related StackOverflow question,它帮助我找到了这个答案。也许这对你有一些用处。

    【讨论】:

    • 非常感谢您,我编辑了我的问题以包括我在您的帮助后所做的更改,它似乎运行良好,错误消失了。当您说“不要忘记使用 async/await”时,您指的是这一行: const response = await loadListings();还是说我还需要等待或其他地方?
    • 乐于助人!是的,我指的是const response = await loadListings();,我应该更清楚。只是想把它说出来,因为它很容易错过。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多