如何取消 React Native 中的 Image.getSize() 请求?

pji*_*ers 6 javascript reactjs react-native

我正在使用 React Native 的Image.getSize(uri, (width, height) => {})方法来获取远程图像的尺寸并将其设置为组件的状态setState()

componentDidMount() {
  Image.getSize(this.props.uri, (width, height) => {
    this.setState({ width, height })
  })
}
Run Code Online (Sandbox Code Playgroud)

但是,有时组件在getSize()请求返回之前卸载,这会导致setState()调用时出现以下错误:

无法对卸载的组件执行 React 状态更新。这是一个空操作,但它表明您的应用程序中存在内存泄漏。要修复,请取消 componentWillUnmount 方法中的所有订阅和异步任务。

我知道可以跟踪组件的安装状态以防止setState()调用,但显然这被认为是一种反模式。

鉴于getSize()没有提供取消挂起请求的方法,是否还有其他方法可以实现这一点?

dpn*_*lte 2

我遇到了同样的问题。对我有用的是包含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 };
};
Run Code Online (Sandbox Code Playgroud)

然后你可以在你的组件中使用它,如下所示:

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(); 
      }
    }
  });
}
Run Code Online (Sandbox Code Playgroud)