【问题标题】:Closing a useEffect Memory Leak in React-Native在 React-Native 中关闭 useEffect 内存泄漏
【发布时间】:2021-03-07 13:06:29
【问题描述】:

从我的 expo 应用程序中的一组地图导航到另一组时,如果我在地图加载完成之前导航,我经常会收到此错误:

警告:无法对未安装的组件执行 React 状态更新。这是一个空操作,但它表明您的应用程序中存在内存泄漏。要解决此问题,请取消 %s 中的所有订阅和异步任务。%s,一个 useEffect 清理函数

如何解决这个内存泄漏?

下面是我的代码:

function MapsScreen({navigation}) { 

const [user_latitude, setUserLatitude] = useState(0)
const [user_longitude, setUserLongitude] = useState(0)
const [position_error, setPositionError] = useState(null)
   
useEffect(() => {
  navigator.geolocation.getCurrentPosition(position => { 
    setUserLatitude(position.coords.latitude);
    setUserLongitude(position.coords.longitude);
    setPositionError(null);
  }, 

  error => setPositionError(error.message),
  {enableHighAccuracy: true, timeout: 20000, maximumAge: 2000}
  ); 
});

【问题讨论】:

    标签: react-native memory-leaks react-hooks use-effect


    【解决方案1】:

    原因: You will get this warning when your component is unmounted from the memory and some async task is in the process like you make a network call and tries to leave the screen before resolving the promise.

    解决方案To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.

    问题的解决方案:查看代码时,当组件尝试卸载时,您正在更改状态,您必须使用带有 useEffect 挂钩的清理功能,添加一个标志在setUserLatitudesetUserLongitudesetPositionError之前确保组件没有从内存中卸载

    function MapsScreen({navigation}) { 
    
    const [user_latitude, setUserLatitude] = useState(0)
    const [user_longitude, setUserLongitude] = useState(0)
    const [position_error, setPositionError] = useState(null)
       
    useEffect(() => {
      let mounted = true // Add this 
      navigator.geolocation.getCurrentPosition(position => { 
       if(mounted){ // Add this
        setUserLatitude(position.coords.latitude);
        setUserLongitude(position.coords.longitude);
        setPositionError(null);
        }
      }, 
    
      error => setPositionError(error.message),
      {enableHighAccuracy: true, timeout: 20000, maximumAge: 2000}
      ); 
    
     return () => {
      mounted = false // add this
     }
    }, []);
    

    阅读更多关于它的信息Clean up function

    【讨论】:

    • 仅此而已?
    • 不是所有的,但你需要一个清理功能来消除这个警告。
    • 您认为还需要多少代码才能使其工作?
    • 这个return () => { console.log("cleaned up"); // add this clean up function }
    • 已添加。还有什么特别的吗?
    【解决方案2】:

    我同意 Waheed 的回答, 顺便说一句,如果您的代码中已经有 react-navigation v5.x 会更容易, 很简单,只需使用useFocusEffect 方法,该函数仅在屏幕聚焦时执行。我举例说明使用isActive 标志检查器添加第二次检查。

    import React, { useEffect, useState } from 'react'
    import { useFocusEffect } from '@react-navigation/native'
    
    function MapsScreen({ navigation }) {
      const [user_latitude, setUserLatitude] = useState(0)
      const [user_longitude, setUserLongitude] = useState(0)
      const [position_error, setPositionError] = useState(null)
    
      useFocusEffect(
        React.useCallback(() => {
          let isActive = true
    
          const fetchGeoPositon = () => {
            navigator.geolocation.getCurrentPosition(
              position => {
                if (isActive) {
                  setUserLatitude(position.coords.latitude)
                  setUserLongitude(position.coords.longitude)
                  setPositionError(null)
                }
              },
    
              error => isActive && setPositionError(error.message),
              { enableHighAccuracy: true, timeout: 20000, maximumAge: 2000 }
            )
          }
    
          fetchGeoPositon()
    
          return () => {
            isActive = false
          }
        }, [])
      )
    }
    

    https://reactnavigation.org/docs/use-focus-effect/

    【讨论】:

    • useEffect和useFocusEffect有什么区别?
    • 我正在使用 RN 版本 5。它会使挂载/卸载更高效吗?
    • @MK_Pierce,是的,我已经在我当前的项目中尝试过。 useFocusEffect 效果很好。与 useEffect 相比,它确实会监听已挂载和未挂载的屏幕行为。
    • useEffect 是来自 React 本身的效果 Hooks。为了便于理解,react 中的 useEffect 类似于 componentDidMount、componentDidUpdate 和 componentWillUnmount 的组合。另一方面,useFocusEffect 来自 React-Navigation 包,而不是来自 React。当屏幕聚焦或模糊时,它会产生副作用。
    • 或者,你也可以使用 react-navigation 中的`useIsFocused`,类似于简单的钩子来获取屏幕的焦点状态。 -> import { useIsFocused } from '@react-navigation/native' 你可以在这里阅读更多内容兄弟:reactnavigation.org/docs/use-is-focused
    猜你喜欢
    • 1970-01-01
    • 2021-01-28
    • 1970-01-01
    • 2021-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-28
    • 2013-03-29
    相关资源
    最近更新 更多