I have a React Native component that makes an Image.getSize
request for each image in the component. Then within the callback of the Image.getSize
requests, I set some state for my component. That all works fine, but the problem is that it's possible for a user to transition away from the screen the component is used on before one or more Image.getSize
requests respond, which then causes the "no-op memory leak" error to pop up because I'm trying to change state after the component has been unmounted.
So my question is: How can I stop the Image.getSize
request from trying to modify state after the component is unmounted? Here's a simplified version of my component code. Thank you.
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;
I had to implement something similar, I start by initialising a variable called
isMounted
.It sets to
true
when the component mounts andfalse
to when the component will unmount.Before calling
setImgDimens
there's a check to see if the component is mounted. If not, it won't call the function and thus will not update state.Edit: This is the answer that worked for me, but for what it's worth, I had to move the
isMounted
variable to outside theSomeComponent
function for it to work. Also, you can just use a regular variable instead ofcreateRef
to create a reference, etc.Basically, the following worked for me: