Javascript react router v4:使用自定义挂钩而不是提示防止转换

Javascript react router v4:使用自定义挂钩而不是提示防止转换,javascript,react-router,history.js,html5-history,Javascript,React Router,History.js,Html5 History,在react routerv3中,我一直使用检查表单是否有未保存的更改,如果有,则返回false,以防止转换。然后,我将显示一个自定义引导模式对话框,其中有3个按钮:保存更改、放弃更改和停留在此处 我无法使用react routerv4的Prompt组件来执行此操作,因为无法自定义浏览器确认对话框中显示的按钮。似乎他们放弃了任何取消转换的方法,只允许您在浏览器确认对话框中请求用户批准转换 我试图在代码中查找提示符,但是,这并没有让我知道如何设置v3风格的路由离开挂钩 这是否可能,或者react路

react router
v3中,我一直使用检查表单是否有未保存的更改,如果有,则返回
false
,以防止转换。然后,我将显示一个自定义引导模式对话框,其中有3个按钮:保存更改、放弃更改和停留在此处

我无法使用
react router
v4的
Prompt
组件来执行此操作,因为无法自定义浏览器确认对话框中显示的按钮。似乎他们放弃了任何取消转换的方法,只允许您在浏览器确认对话框中请求用户批准转换

我试图在代码中查找
提示符
,但是,这并没有让我知道如何设置v3风格的路由离开挂钩


这是否可能,或者
react路由器
devs出于某种原因故意决定删除此功能?

我认为这是不可能的。react-router-v4使用一个名为的包,该包依次使用HTML5历史api。历史api只会在您点击后退按钮(onpopstate)时通知您,如果您仔细想想,这很有意义,因为您不希望给网站不允许您在页面之间移动的功能

您所能做的最好的事情是,创建一个提示,要求用户确认,但这正是react router公开给您使用的内容

通过monkey patching react router的内部历史对象,您可能会获得一些想要的功能,这样您就可以添加自己的行为。但有一个警告,这只会在您对路由器的
组件和好友做出反应时起作用,所以您将无法拦截刷新和其他您可能需要的内容

如果您想这样做,请告诉我,我可以为您提供一些有关如何工作的见解或代码示例,我将更新我的答案。

根据,您可以替换
窗口。用您喜欢的任何内容确认

默认情况下,window.confirm用于向用户显示提示消息。如果您需要重写此行为(或者如果您使用的是createMemoryHistory,它不采用DOM环境),请在创建历史对象时提供getUserConfirmation函数

因此,如果您想使用自己的对话框,类似这样的内容将帮助您完成:

const history = createHistory({
  getUserConfirmation(message, callback) {
    showMyCustomDialog(message)
      .then(result => callback(result === 'The YES button'))
  }
})
这意味着,您设置的任何
getUserConfirmation
消息都将在整个会话中设置,但您可以将其提取到导航阻止层,该层包含对话框的其他详细信息,例如标题、按钮文本、颜色等

或者,您可以劫持
消息
参数并将其用于对话框配置,尽管这可能有点难闻。但这并不是一个完美的系统,所以你做的任何事情都可能有点像黑客

React Router v4允许您在创建路由器时传递此方法(请参阅):


可以使用
提示符
显示自定义对话。信用和详细解释

Prompt
需要一个消息道具,在这里我们可以使用一个自定义函数进行对话,它应该返回
false
以防止导航

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>
  )

} 
constblockingpage=()=>{
const[block,setBlock]=使用状态(true);
常量阻塞导航=(nLocation)=>{
//nLocation提供下一个位置对象
/**
*您的自定义逻辑
*
**/
//需要阻止导航
返回错误
} 
返回(
)
} 

但是react-router-v3如何防止转换?它还使用历史记录,所以除非他们从历史记录中删除此功能,否则我无法理解您的意思。谢谢,我还没有发现这一点!这当然是真的,我所做的任何事情都可能是一个黑客。对于旧的路由离开钩子来说,情况并非如此。一种不太老练的方法是使用
消息
作为对象键,并建立一个可能的导航拦截器字典。例如,
blockers={myBlocker:cb=>dialog.then(cb)}
然后在用户确认函数中,调用
blockers[message](回调)
。我最近进行了v3=>v4升级,发现我只使用过一个对话框,有时完全阻止导航(例如,当显示模式时),因此将对话框代码烘焙到确认函数中就足够了。我敢肯定,如果你想扩大它的能力,这个项目将需要公关!啊,太酷了,我不确定这是否是我在某种程度上暗示提交OPDOC时的一个功能,但它缺少了一个事实,即您可以
返回false
来阻止导航
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>
  )

}