Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Downloads of unmounted images aren't canceled #290

Open
devxzero opened this issue May 24, 2020 · 7 comments · May be fixed by #996
Open

Downloads of unmounted images aren't canceled #290

devxzero opened this issue May 24, 2020 · 7 comments · May be fixed by #996

Comments

@devxzero
Copy link

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. #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.)

@mbrevda
Copy link
Owner

mbrevda commented May 24, 2020

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!

@c5inco
Copy link

c5inco commented Jun 24, 2020

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.

@hornetDC
Copy link

hornetDC commented Aug 5, 2020

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

@mbrevda
Copy link
Owner

mbrevda commented Aug 5, 2020

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!

@yulbka
Copy link

yulbka commented Jan 29, 2021

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?

@mbrevda
Copy link
Owner

mbrevda commented Jul 7, 2022

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 mbrevda linked a pull request Oct 5, 2023 that will close this issue
@mbrevda
Copy link
Owner

mbrevda commented Oct 5, 2023

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants