redwood
redwood copied to clipboard
WIP(router): Add useBlocker hook
New version of #9820 based on @Tobbe 's input
Conceptually it would be used like this:
const PostForm = (props: PostFormProps) => {
const form = useForm<FormPost>()
const blocker = useBlocker(form.formState.isDirty)
return (
<div className="rw-form-wrapper">
<Form formMethods={form} onSubmit={onSubmit} error={props.error}>
State {blocker.state}
{blocker.state === 'BLOCKED' ? (
<div>
<button type="button" onClick={() => blocker.confirm()}>
Confirm
</button>
<button type="button" onClick={() => blocker.abort()}>
Abort
</button>
</div>
) : null}
...
</Form>
</div>
)
}
Help wanted
I'm currently stuck with the history.replaceState logic and I'm opening this PR just to see if someone has an idea what's happening here. Feel free to comment if you have a suggestion. I'd be happy to try it out.
Behaviour
The new navigation provider is patching the global history object to include the custom checks. If any blocker is true
it shouldn't invoke the pushState and keep the current location but it somehow desyncs the active route from the URL.
The blocker prevents the new page from being loaded but the window.location changes and on the next navigation it doesn't block anymore because it doesn't know it's on a page that should be blocked.
globalThis.history.pushState = function pushState(
data: any,
unused: string,
url?: string | URL | null
) {
const currentLocation = new URL(globalThis.location.href)
const newLocation = new URL(globalThis.location.origin + url)
if (
currentLocation.pathname === newLocation.pathname &&
currentLocation.search === newLocation.search &&
currentLocation.hash === newLocation.hash
) {
return
}
const blocked = blockers.some(({ check }) =>
check(currentLocation, newLocation, NavigationMethod.PUSH, () => {
originalPushState(data, unused, url)
})
)
if (!blocked) {
originalPushState(data, unused, url)
}
}
For anyone wondering about this PR. I haven't been able to get back to this but it's still on my list.
Lots of work on this @xmaxcooking Thank you! Checking in to see if this is something you'd like us to keep open — fine on our end.
Lots of work on this @xmaxcooking Thank you! Checking in to see if this is something you'd like us to keep open — fine on our end.
feel free to close it. the discussion with @Tobbe helped bring this into the right direction but at this point I'll open it again when I have a working state.
Understood. We'd welcome you opening it up again in the future!