useBeforeLeave event.defaultPrevented not updated
Describe the bug
When you use useBeforeLeave multiple times, each listener receives a copy of the event, therefore an early listener cannot know if a later listener did call preventDefault.
Reproduction:
useBeforeLeave(evt => requestAnimationFrame(() => console.log(evt.defaultPrevented)));
useBeforeLeave(evt => evt.preventDefault());
// Logs: false
Your Example Website or App
Reproduction code in description
Steps to Reproduce the Bug or Issue
- Create a solid start project
- Add the reproduction code from above to the App component
- Open the project in the browser
- Click on a Solid-Router powered link
- Check the browser console
Expected behavior
You should be able to read the up-to-date value of defaultPrevented. The above reproduction should log true.
Screenshots or Videos
No response
Platform
- OS: Linux
- Browser: Zen
- Version: 1.12.3b (Firefox 138.0.1)
Workaround
This lets you attach a listener early, yet read the defaultPrevented late:
import { useBeforeLeave } from "@solidjs/router";
import { createRoot } from "solid-js";
export const useBeforeLeaveLate = (
listener: Parameters<typeof useBeforeLeave>[0],
) =>
useBeforeLeave(() =>
createRoot((dispose) =>
useBeforeLeave((e) => {
dispose();
listener(e);
}),
),
);
Reason
https://github.com/solidjs/solid-router/blob/30f08665e87829736a9333d55863d27905f4a92d/src/lifecycle.ts#L23
@Brendan-csel Do you by chance remember the reason for implementing the useBeforeLeave event in an immutable fashion 😁?
I just needed something to work for my use-case - which only ever involved a single listener anyway.
Is there even a guarantee of the order listeners will be called? Or is it just a lucky side-effect of the current implementation and subject to change.