react-image icon indicating copy to clipboard operation
react-image copied to clipboard

Downloads of unmounted images aren't canceled

Open devxzero opened this issue 5 years ago • 7 comments

Background info: When the browser starts to download an image via a plain html img tag, and the img tag is removed from the DOM while the image is being downloaded or even before the image download starts, the browser will continue to download the image. This problem doesn't occur in plain non-JS server side rendered application, because a new HTTP page request will abort all images. But for JavaScript applications, the images have to be aborted manually by setting the src attribute to an empty-string. More info about this problem is shown here: https://stackoverflow.com/questions/59270779/react-downloads-pending-images-of-previous-render If no solution would be implemented, this would cause the downloading (and loading) of images to be stacked/accumulated invisibly in the browser, which causes bandwidth waste. It also causes a delay in the rendering of new pages, because the browser will first download all images from all previously closed pages. (Personally, I think this is a flaw in the DOM standard. )

Fixed in React-Image since 2.1.1? There was a pull request which would automatically cancel image download when those images were umounted. https://github.com/mbrevda/react-image/pull/223 Which included a plain JavaScript demo to demonstrate that cancellation is possible in the DOM: https://jsbin.com/zakeqaseru/1/edit?output

A solution was implemented in React-Image 2.1.0 with a fix followed in 2.1.1: https://github.com/mbrevda/react-image/blob/master/CHANGELOG.md

But React-Image doesn't seem to cancel the download on unmount. You can verify this here: https://codesandbox.io/s/upbeat-hopper-kucou https://kucou.csb.app/

(Apart from the image cancellation problem, for some unknown reason, CodeSandbox gives an error for React-Image 2.x, but does work for 4.x. But I have also tried it locally, were is does run, but still has the cancellation problem.)

devxzero avatar May 24 '20 15:05 devxzero

Thanks for this, all valid points. V4 is super flexible in how image downloading is done which has the downside of making it harder to predict what the right cancelation methodology would be. Let me give this some thought on how to go about it. Until then, ideas are welcome!

mbrevda avatar May 24 '20 16:05 mbrevda

Not sure this is a related issue, but I'm seeing this manifested in other ways when combining react-image with libraries like react-virtualized:

Output in console:

Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.

c5inco avatar Jun 24 '20 16:06 c5inco

@c5inco correct. I encountered similar issue with unmounting components.

hornetDC avatar Aug 05 '20 11:08 hornetDC

Thanks for the feedback guys! The complexity here designing is an API which returns cancel() in addition to a Promise, while still allowing the Promise to be easily overridden when a custom implementation is required. While we would want to control calling cancel mechanism, we cannot be certain that one actually exists...

Have some possible ideas, but those require a breaking change. Open to API/code suggestions!

mbrevda avatar Aug 05 '20 11:08 mbrevda

I also have output in console Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
Any news about this issue?

yulbka avatar Jan 29 '21 08:01 yulbka

The error has been depreciated in React 18 and should no longer show.

Regarding the issue at hand, I'm thinking of adding a .abort() to the returned promise which can be called on unmount to abort downloading the current image. Not the cleanest of solutions (adding a prop to an instance of a known API) but should be fine. Would require users of a custom imageFetcher to implement their own abort mechanism.

Thoughts?

mbrevda avatar Jul 07 '22 09:07 mbrevda

A PR has been opened to address this. There is a link with a preview build - it would be great if you could download and manually install that and test. Thanks!

To test, download and in your projects directory run npm i ../path/to/download/preview.tgz and run your project

mbrevda avatar Oct 05 '23 14:10 mbrevda