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

[bug] ToastId can't be reused! #534

Closed
derek-groupmail opened this issue Oct 23, 2020 · 10 comments · Fixed by #554, newerton/gobarber-frontend#11 or newerton/gostack-modulo07#17
Closed
Assignees

Comments

@derek-groupmail
Copy link

Do you want to request a feature or report a bug?

Bug report!

What is the current behavior?

Thanks for the great library, this is very slick and professional!
Unfortunately though, I think I've uncovered a bug that badly affects how I want to use it.

Basically, I'm using toastIds in order to prevent duplicate toasts from being displayed.

This works pretty well usually but on occasion it appears that when a toast expires and therefore disappears from view that behind the scenes the toastId doesn't actually get cleared from memory (or it may get removed but mistakenly added back somehow). When this happens, it has the effect of preventing any further toasts with that same toastId from ever being displayed again! Even though the toast has obviously expired and long gone and that toastId ought to be able to be re-used, it can't!

If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem. Your bug will get fixed much faster if we can run your code and it doesn't have dependencies other than React. Paste the link to your CodeSandbox (https://codesandbox.io/s/new) example below:

I've found the following helps to reproduce the problem:-

The issue tends to appear when a toast has expired and is in the process of completing its exit animation (in my case I'm using 'Slide'). If another toast with the same toastId is launched just at the exact time that the first toast completes its exit animation, then it looks like the new toast appears momentarily sliding in but then doesn't complete its entrance animation and suddenly disappears! When I see that happening, I know that the bug has occurred and that at this point the toastify system thinks that the toast with that toastId is 'active' even though it's no longer being displayed and will also never expire and so that toastId is now permanently locked as 'active' preventing any other toasts with that same id from being launched.

So, it would seem that there is some interaction or interference between the new toast being launched and the previous toast exiting when they both have the same toastId, possibly due to some kind of race condition.

When the issue happens, if I query the status of that toast with toast.isActive(myToastId) then it will return true even though the toast has obviously expired (i.e. it's not being displayed) and should have been removed from memory. This proves that toastify system has either incorrectly held on to the toastId that just exited or else the toast that just exited has corrupted somehow the newly introduced toast, making it disappear but retaining its toastId in memory so that it will never expire.

The issue is difficult to reproduce accurately, but happens often enough to be troublesome. I can typically reproduce it about one in every 10 (or less) attempts, but the timing is key.

Unfortunately I don't have a sandbox for this at the moment, but I'm not sure creating a sandbox for it would do any good because it seems to be mostly a timing issue, which might be hard to reproduce programmatically - you have to create a new toast just as the old one is exiting. I'm pretty sure this should be demonstrable with any simple toastify implementation if you time it right. I don't think it's due to any issue with my implementation as I'm using it in a fairly simple and straightforward way.

It looks like possibly this issue may be related to this one - "Recreate Toast after hiding using toastId #483" ?

What is the expected behavior?

I would expect that when a toast with a particular toastId expires that same toastId would be available for subsequent re-use.

I would expect that there would be no interactions between two toasts, where the first toast is exiting and the second toast is starting up, where both toasts have the same toastId. The first toast exiting should not corrupt or affect the second toast.

Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?

I'm using react v16.9.0 and react-toastify v6.0.9
This is my first time using react-toastify so no previous history.

Thanks!

@derek-groupmail derek-groupmail changed the title ToastId can't be reused! [bug] ToastId can't be reused! Nov 30, 2020
@guicara
Copy link

guicara commented Dec 7, 2020

Hello,

I have exactly the same issue and the same question as you.
I also don't know if the current behavior is a bug or not.

@fkhadra fkhadra added the bug label Dec 20, 2020
@fkhadra fkhadra self-assigned this Dec 20, 2020
@fkhadra
Copy link
Owner

fkhadra commented Dec 20, 2020

Hey, thanks for reporting. It's indeed a bug, I'm working on a fix.

@fkhadra
Copy link
Owner

fkhadra commented Dec 23, 2020

@derek-groupmail @guicara do you have an easy way to reproduce the issue ? thx

fkhadra added a commit that referenced this issue Dec 29, 2020
@fkhadra fkhadra added the Merged in next Merged but not live label Dec 29, 2020
@fkhadra fkhadra mentioned this issue Dec 29, 2020
fkhadra added a commit that referenced this issue Jan 25, 2021
## 💥 Breaking changes

- dependency to react-transition-group has been removed #514
- the `duration` parameter has been removed from `cssTransition`. Css animations just works now out of the box. Check the codesanbox below  
- the border-radius has been increased a bit

##  🚀 Features

- Css animation just works! 
[![View](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/react-toastify-animatecss-jxrx9?fontsize=14&hidenavigation=1&theme=dark&view=preview)

- add a way to load the CSS without a CSS loader
[![Edit react-toastify-inject-style](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/react-toastify-inject-style-qfg0l?fontsize=14&hidenavigation=1&theme=dark)
- specify swipe direction, close #512 . Thanks to @denydavy
[![Edit react-toastify-drag-y](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/react-toastify-drag-y-lh88i?fontsize=14&hidenavigation=1&theme=dark)
- bundle size reduced from ~7k to ~5k!
- remove the dependency on prop-types.

## 🐛 Bugfix

- fix #541 apply pauseOnFocusLoss on first render
- fix #538 react-dom should be a peer dep
- fix #530 change id generation
- fix #534 #483 toastId cannot be reused
- fix #511 by removing react-transition-group
- fix #550 Unable to select text inside inputs when a toast is open
- fix #555 The toast timer starts after you click on the toast
@guicara
Copy link

guicara commented Jan 27, 2021

Hello @fkhadra,

Thank you for this new release (7.0.0)!

I have upgraded the package on my project. Unfortunately, the issue is not resolved 😢

I will try to reproduce the bug on a codepen this week.

In the meantime, please find below a screen recording of the issue on my project. The user can download files by clicking on a button. When a download starts a toast is displayed. Each toast has a custom toastId equal to the UUID of the file. As you can see on the video, the download of the first and second files display the toasts. But, when I download again the same file, the toast is not displayed. However, the file is correctly downloaded in the background.

I've also tried to programmatically remove the toast when the download is completed using toast.dismiss.

react-toastify-issue-534.mp4

@fkhadra
Copy link
Owner

fkhadra commented Jan 27, 2021

Damn I'll reopen the issue then

@skrivanos
Copy link

@fkhadra Issue still looks closed and I can confirm there's still oddities with the toast ids, leading to toasts not being shown in certain cases.

@fkhadra
Copy link
Owner

fkhadra commented Apr 23, 2021

Hey @skrivanos can you help me reproduce the issue on codesandbox? This would be really helpful 🙏

@Sh1d0w
Copy link

Sh1d0w commented Jun 8, 2021

I can confirm that it still happens on version 7.0.3

How it happens for me is that I have an app that have toast notifications triggered by events coming from websockets.

If I open two tabs and trigger a notification from the first one to the second one which is in background and then switch to it I can see the notification properly showing. Then I go to the first tab trigger cancel which closes the notification in the second tab and then trigger open again. Switching to the second tab does not show the notification anymore since it has the same toastId for that notification type.

I am not sure how I can setup codesandbox with this case as it is quite complicated and specific to our project, but I hope it sheds some light on the possible cause.

EDIT: This seems to happen only when the tab is in background, e.g. not in focus. When it is on focus it works ok.

@unematiii
Copy link

There is definitely something going on when browser is activated from background (throttling of timers?). So I switched from using my own constant ID-s to one generated by this API while storing them in ref object. But now, sometimes when browser is activated again toast.dismiss(id) or even toast.dismiss() does not nothing, toast just wont hide...

@fkhadra fkhadra mentioned this issue Jun 11, 2023
@fkhadra fkhadra added the Merged in next Merged but not live label Aug 1, 2023
@RicFer01
Copy link

RicFer01 commented Oct 12, 2023

If I've 2 buttons, let's say success and error, I'm also using the toastId, when I click quickly on success, error and after success, the last success is not displayed, I think because it remains in memory for certain amount of time and since it's the same toastId, it's not displayed.
With 3 buttons clicked consecutively, the problems is not present, because the last one in memory will be never equal to the first one I clicked, since there is one more step.
For now I fixed it programmatically, even if it's not ideal, it works.
Any updated on this bug?

@fkhadra fkhadra closed this as completed Jan 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment