我正在使用React Native的Image.getSize(uri, (width, height) => {})
方法来获取远程图像的尺寸,并使用setState()
将其设置为组件的状态:
componentDidMount() {
Image.getSize(this.props.uri, (width, height) => {
this.setState({ width, height })
})
}
但是,有时会在返回getSize()
请求之前卸载组件,这会在调用setState()
时导致以下错误:
无法在已卸载的组件上执行React状态更新。这是空操作,但它表明应用程序中发生内存泄漏。要解决此问题,请取消componentWillUnmount方法中的所有订阅和异步任务。
我了解可以跟踪组件的安装状态以防止进行setState()
调用,但是显然this is considered an antipattern.
假设getSize()
没有提供取消未决请求的方法,还有其他方法可以实现吗?
答案 0 :(得分:1)
我遇到了同样的问题。
对我有用的是将Image.getSize
包装在一个诺言中:
export type CancelPromise = ((reason?: Error) => void) | undefined;
export type ImageSize = { width: number; height: number };
interface ImageSizeOperation {
start: () => Promise<ImageSize>;
cancel: CancelPromise;
}
const getImageSize = (uri: string): ImageSizeOperation => {
let cancel: CancelPromise;
const start = (): Promise<ImageSize> =>
new Promise<{ width: number; height: number }>((resolve, reject) => {
cancel = reject;
Image.getSize(
uri,
(width, height) => {
cancel = undefined;
resolve({ width, height });
},
error => {
reject(error);
}
);
});
return { start, cancel };
};
然后您可以像这样在组件中使用它:
const A: React.FC = () => {
const [size, setSize] = useState<{width: number, height: number} | undefined>(});
useEffect(() => {
let cancel: CancelPromise;
const sideEffect = async (): Promise<void> => {
try {
const operation = getImageSize(uri);
cancel = operation.cancel;
const imageSize = await operation.start();
setSize(imageSize);
} catch(error) {
if (__DEV__) console.warn(error);
}
}
sideEffect();
return () => {
if (cancel) {
cancel();
}
}
});
}