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
Fix flaky logout #185
Fix flaky logout #185
Conversation
Just noticed the logout POST request is still aborted. This only happens on Playwright tests. //...
await page.getByRole('link', { name: user.name ?? user.username }).click()
await page.getByRole('menuitem', { name: /logout/i }).click()
await expect(page).toHaveURL(`/`) // 👈 This doesn't help
await page.goto('/login')
await expect(page).toHaveURL(`/login`)
//... Edit: I'll open an issue just for test-related stuff. |
app/root.tsx
Outdated
className="rounded-b-3xl px-7 py-5 outline-none radix-highlighted:bg-night-500" | ||
onClick={e => submit(e.currentTarget)} | ||
onClick={e => { | ||
e.preventDefault() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason this is not the only line changed in the PR? Why can't we keep the action
and method
and use submit(e.currentTarget)
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whoops, never mind. I know why. I wonder if we could change this to e.stopPropagation
to prevent the menu from closing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let me try that out
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure how the Radix UI internals work, but my suspicion is that, because the form takes up all of the <DropdownMenu.Item asChild>
's behavior, having an onClick on it is already too late, because it'll send the close comand to the <DropdownMenu.Portal>
.
Adding onClick={e => e.stopPropagation()}
to the button works 👌
Should be ok now 👌 ✅ Detached from DOM, so no console warning |
I believe I've solved it another way that I'm happier with. Can you try it out and let me know if this fixes it. I also added a logout button to the profile page because otherwise you can't logout if JS doesn't load. |
Oh, I missed something: a61c713 |
Seems pretty solid 👌 |
Awesome! |
Thank you for your help |
submit(e.currentTarget)
pushes the form's submission task to the macrotask queue in the event loop to process later. The click event bubbles up to<DropdownMenu.Portal>
which will remove itself from the DOM by pushing the removal task to the macrotask queue.The first task in the queue, the form's submission, is sent to the call stack and processed. This results in an asynchronous network request the browser asks the OS to make and await for and becomes associated with that DOM element.
While the browser waits for the OS to handle that network request, the second task in the macrotask queue, the removal of
<DropdownMenu.Portal>
and its<form>
child, is sent to the call stack and processed.This creates a race condition:
<form>
from the DOM (and the subsequent network request cancelation associated with it) succeeds first, the network request is canceled and the logout might fail, depending on whether the request has already been sent or not.I think 😄
Fix
Detach the form submission from its DOM element:
Result
Form submission canceled because the form is not connected
console warningsScreenshots
Network tab:
Console: