通过setRouteLeaveHook手动删除路由离开挂钩集

时间:2016-03-12 14:47:39

标签: reactjs react-router react-redux

我想知道如何手动删除特定路线的setRouteLeaveHook。这个page表示在大多数情况下我不应该手动执行此操作,但如果需要,我也不会提及如何执行此操作。

  

在大多数情况下,您不需要手动拆除路线离开挂钩。离开相关路线后,我们会自动删除所有附加的路线离开挂钩。

原因可能最好通过例子解释。

class Editor extends Component {

componentDidMount(){
    const { dispatch, dirty, route } = this.props;
    const { router } = this.context;
    router.setRouteLeaveHook(route, this.routerWillLeave.bind(this));
}

routerWillLeave(nextLocation){
  console.debug('routerWillLeaveCalled -> ', this.props);
  let { dirty, dispatch, resetForm } = this.props;
  const { router } = this.context;
  if (dirty) {
    let dialog = {
      id: Date.now(),
      showTitle: true,
      titleContent: 'Unsaved Changes',
      titleIcon: 'fa fa-warning',
      content: <span>You have <strong>unsaved</strong> changes! <strong>Discard</strong> them?</span>,
      type: 'confirm',
      handleCloseClick: (e) => {
        e.preventDefault();
        dispatch(closeDialog());
      },
      acceptBtn: {
        title: 'Okay',
        handler: (e) => {
          e.preventDefault();
          resetForm();
          console.debug('handler dirty ->', dirty);
          dispatch(push(nextLocation));
          // dispatch(closeDialog());
        }
      },
      denyBtn: {
        title: 'Deny',
        handler: (e) => {
          e.preventDefault();
          dispatch(closeDialog());
        }
      }
    }
    dispatch(addDialogWindow(dialog));
    dispatch(openDialog(false, (e) => dispatch(closeDialog()), false));
    return false;
  }
  return true;
}

}

我遇到的问题是acceptBtn。调用redux-forms resetForm()函数后,编辑器组件尚未更新(使用新的道具,我不知道为什么),这意味着当dispatch(push(nextLocation));resetForm()时,dirty仍然设置为true调用。

看看流程是什么样的:

  1. 点击链接会产生不同的路线。
  2. 第一次调用routerWillLeave。它会调度一些显示我的对话框的动作(它有两个按钮接受和拒绝)。
  3. 当第一次点击acceptBtn时会发生什么是再次调用routeWillLeave(因为它仍然挂钩)。出于某种原因,即使已调度dirty == true,组件仍未更新,这意味着dirty == false并且再次执行相同的代码块。
  4. 第二次点击acceptBtn现在会再次触发routerWillLeave,但这次acceptBtn因此它返回true并且路线会按原样改变。
  5. 以下是第一次点击action @ 01:26:08.101 redux-form/RESET action @ 01:26:08.105 @@router/CALL_HISTORY_METHOD action @ 01:26:08.117 ADD_DIALOG_WINDOW action @ 01:26:08.127 OPEN_DIALOG 后发送的操作。

    action @ 01:26:02.235 ADD_DIALOG_WINDOW 
    action @ 01:26:02.239 OPEN_DIALOG 
    action @ 01:26:08.101 redux-form/RESET 
    action @ 01:26:08.105 @@router/CALL_HISTORY_METHOD 
    action @ 01:26:08.117 ADD_DIALOG_WINDOW 
    action @ 01:26:08.127 OPEN_DIALOG 
    action @ 01:43:10.358 redux-form/RESET 
    action @ 01:43:10.363 @@router/CALL_HISTORY_METHOD 
    action @ 01:43:10.372 @@router/LOCATION_CHANGE 
    action @ 01:43:10.670 redux-form/DESTROY 
    action @ 01:43:10.676 redux-form/DESTROY 
    

    这是在第二次点击之后。

    var image = document.querySelector('img'); 
    
    image.addEventListener('click', onClick, true);
    
    function onClick(event){
    		var imageBoundingRect = image.getBoundingClientRect();
        
        var x = event.pageX - imageBoundingRect.left;
    
        // We are not using the y co-ordinate but this is how you would get it.
        var y = event.pageY - imageBoundingRect.top;
    
    	if (x >= 345 && x <= 380){
          alert('Clicked on the yellow pen.')
        }
    }

    因此,我想要做的是删除acceptBtn的处理函数中的钩子。这可能/可以吗?或者有什么我做错了,或者更好的方法来实现这个目标?

2 个答案:

答案 0 :(得分:4)

删除setRouteLeaveHook挂钩。

let remove = router.setRouteLeaveHook(route, (nextLocation) => {
   remove()
})

答案 1 :(得分:0)

似乎这是调度调用的定时执行问题。在超时0中包装位置分派修复了问题。

      acceptBtn: {
        title: 'Okay',
        handler: (e) => {
          e.preventDefault();
          resetForm();
          // Wait for call stack to unwind and then execute
          // the following which will now have the updated values.
          setTimeout(() => {
            dispatch(push(nextLocation));
            dispatch(closeDialog());
          }, 0);
        }
      },