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



我有一个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;

我必须实现类似的东西,我首先初始化一个名为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变量移动到SomeComponent函数外部的才能使其工作。此外,您可以只使用一个正则变量而不是createRef来创建引用等。

基本上,以下对我有效:

let isMounted;
const SomeComponent = (props) => {
const setImgDimens = (arr) => {
arr.forEach((arrItem, i) => {
if (arrItem.imgPath) {
const uri = `/path/to/${arrItem.imgPath}`;
Image.getSize(uri, (width, height) => {
if (isMounted) { // Added this check.
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(() => {
isMounted = true;
setImgDimens(arr);
return () => {
isMounted = false;
}
}, []);
};

最新更新