卸载React Native组件时如何清除Image.getSize请求?

时间:2020-03-24 15:20:32

标签: reactjs react-native react-component react-state react-component-unmount

我有一个React Native组件,它对该组件中的每个图像进行Image.getSize请求。然后在Image.getSize请求的回调中,为组件设置一些状态。一切正常,但是问题在于,用户有可能在一个或多个Image.getSize请求响应之前从使用组件的屏幕移开,从而导致“无操作内存泄漏”错误弹出,因为我试图在卸载组件后更改状态。

所以我的问题是:卸载组件后,如何阻止Image.getSize请求尝试修改状态?这是我的组件代码的简化版本。谢谢。

const imgWidth = 300; // Not actually static in the component, but doesn't matter.

const SomeComponent = (props) => {
    const [arr, setArr] = useState(props.someData);

    const setImgDimens = (arr) => {
        arr.forEach((arrItem, i) => {
            if (arrItem.imgPath) {
                const uri = `/path/to/${arrItem.imgPath}`;

                Image.getSize(uri, (width, height) => {
                    setArr((currArr) => {
                        const newWidth = imgWidth;
                        const ratio = newWidth / width;
                        const newHeight = ratio * height;

                        currArr = currArr.map((arrItem, idx) => {
                            if (idx === i) {
                                arrItem.width = newWidth;
                                arrItem.height = newHeight;
                            }

                            return arrItem;
                        });

                        return currArr;
                    });
                });
            }
        });
    };

    useEffect(() => {
        setImgDimens(arr);

        return () => {
            // Do I need to do something here?!
        };
    }, []);

    return (
        <FlatList
            data={arr}
            keyExtractor={(arrItem) => arrItem.id.toString()}
            renderItem={({ item }) => {
                return (
                    <View>
                        { item.imgPath ?
                            <Image
                                source={{ uri: `/path/to/${arrItem.imgPath}` }}
                            />
                            :
                            null
                        }
                    </View>
                );
            }}
        />
    );
};

export default SomeComponent;

1 个答案:

答案 0 :(得分:1)

我必须实现类似的东西,首先要初始化一个名为isMounted的变量。

在安装组件时将其设置为true,在卸载组件时将其设置为false

在调用setImgDimens之前,需要检查是否已安装该组件。如果没有,它将不会调用该函数,因此不会更新状态。

const SomeComponent = (props) => {
  const isMounted = React.createRef(null);
  useEffect(() => {
    // Component has mounted
    isMounted.current = true;

    if(isMounted.current) {
      setImgDimens(arr);
    }

    return () => {
      // Component will unmount
      isMounted.current = false;
    }
  }, []);
}

编辑:这是对我有用的答案,但出于其价值,我不得不将isMounted变量移至外部 {{ 1}}函数使其正常工作。另外,您可以使用常规变量代替SomeComponent来创建引用,等等。

基本上,以下内容对我有用:

createRef