卸载 React Native 组件时如何清除 Image.getSize 请求?
How do I clear out an Image.getSize request when unmounting a React Native component?
我有一个 React Native 组件,它对组件中的每个图像发出 Image.getSize
请求。然后在 Image.getSize
请求的回调中,我为我的组件设置了一些状态。一切正常,但问题是用户可能会在一个或多个 Image.getSize
请求响应之前离开使用该组件的屏幕,然后导致 "no-op memory leak" 错误弹出因为我试图在卸载组件后更改状态。
所以我的问题是:如何阻止 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;
}
}, []);
}
Edit:这是对我有用的答案,但为了它的价值,我不得不将 isMounted
变量移动到 outside 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;
}
}, []);
};
我有一个 React Native 组件,它对组件中的每个图像发出 Image.getSize
请求。然后在 Image.getSize
请求的回调中,我为我的组件设置了一些状态。一切正常,但问题是用户可能会在一个或多个 Image.getSize
请求响应之前离开使用该组件的屏幕,然后导致 "no-op memory leak" 错误弹出因为我试图在卸载组件后更改状态。
所以我的问题是:如何阻止 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;
}
}, []);
}
Edit:这是对我有用的答案,但为了它的价值,我不得不将 isMounted
变量移动到 outside 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;
}
}, []);
};