admin管理员组文章数量:1326337
In react-router
v3, I've been using router.setRouteLeaveHook
to check if a form has unsaved changes, and if so return false
to prevent the transition. Then I would display a custom bootstrap modal dialog with 3 buttons: Save Changes, Discard Changes, and Stay Here.
I can't use react-router
v4's Prompt
ponent to do this because it's not possible to customize the buttons shown in a browser confirm dialog. It seems like they got rid of any way to cancel the transition in favor of only allowing you to ask the user to approve the transition in a browser confirm dialog.
I tried looking in the code for Prompt
but it just passes the dialog message to history
, so that doesn't give me any idea how to set up a v3-style route leave hook.
Is it even possible anymore or did the react-router
devs intentionally decide to remove this capability this for some reason?
In react-router
v3, I've been using router.setRouteLeaveHook
to check if a form has unsaved changes, and if so return false
to prevent the transition. Then I would display a custom bootstrap modal dialog with 3 buttons: Save Changes, Discard Changes, and Stay Here.
I can't use react-router
v4's Prompt
ponent to do this because it's not possible to customize the buttons shown in a browser confirm dialog. It seems like they got rid of any way to cancel the transition in favor of only allowing you to ask the user to approve the transition in a browser confirm dialog.
I tried looking in the code for Prompt
but it just passes the dialog message to history
, so that doesn't give me any idea how to set up a v3-style route leave hook.
Is it even possible anymore or did the react-router
devs intentionally decide to remove this capability this for some reason?
3 Answers
Reset to default 3According to the history package docs, you can replace window.confirm
with anything you like:
By default, window.confirm is used to show prompt messages to the user. If you need to override this behavior (or if you're using createMemoryHistory, which doesn't assume a DOM environment), provide a getUserConfirmation function when you create your history object.
So if you want to use your own dialog, something like this should see you through:
const history = createHistory({
getUserConfirmation(message, callback) {
showMyCustomDialog(message)
.then(result => callback(result === 'The YES button'))
}
})
This means that whatever getUserConfirmation
message you set is set for the entire session, but you could abstract it out to your navigation blocking layer that holds additional details for your dialog, e.g. title, button text, colours etc.
Alternatively, you could hijack the message
argument and use it for dialog configuration, though that may smell a bit nasty. But it's not a perfect system so anything you do will probably be a bit of a hack.
React Router v4 allows you to pass this method through when you create your router (see here):
<BrowserRouter getUserConfirmation={yourConfirmationFunction} />
Can use Prompt
to show custom dialogue. Credit and detailed explanation here.
Prompt
requires a message prop, here we can use a custom function for a dialogue and it should return false
to prevent navigation.
const BlockingPage = () => {
const [block, setBlock] = useState(true);
const blockedNavigation = (nLocation) => {
//nLocation gives the next location object
/**
* Your custom logic
*
**/
//required to block navigation
return false
}
return(
<div>
<Prompt when={block} message={blockedNavigation}/>
</div>
)
}
I don't think this is possible. react-router-v4 uses a package called history that in turns uses the HTML5 history api. The history api only notifies you when you hit the back button (onpopstate), If you think about it this makes lots of sense, since you would not want to give a website the power of not letting you move between pages.
The best you can do is the window onbeforeunload event, that creates a prompt for you asking confirmation from the user, but this is exactly what react-router exposes for you to use.
You might get some of the functionality you want by monkey-patching react-router's internal history object, and that way you can add your own behaviour. But there is a caveat, this is only going to work when you react-router's <Link />
ponent and friends, so you will not be able to intercept refreshes and other things you may want.
If you want to go that route, let me know I can give you some insight or code examples about how might that work and I will update my answer.
本文标签: javascriptreactrouter v4 prevent transition with custom hook instead of PromptStack Overflow
版权声明:本文标题:javascript - react-router v4: prevent transition with custom hook instead of Prompt - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742199964a2431742.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论