0

特定のルートの setRouteLeaveHook を手動で削除する方法を知りたいです。このページでは、ほとんどの場合手動でこれを行う必要はないと述べていますが、必要な場合にこれを行う方法については言及していません。

ほとんどの場合、ルート脱退フックを手動で破棄する必要はありません。関連付けられたルートを離れた後、アタッチされたすべてのルート離脱フックを自動的に削除します。

その理由は、おそらく例を通して最もよく説明されています。

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-formsresetForm()関数を呼び出した後、Editor コンポーネントはまだ更新されていません (新しい props で、理由はわかりません)。これは、dispatch(push(nextLocation));呼び出されたときに dirty がまだ true に設定されていることを意味します。

フローは次のようになります。

  1. リンクをクリックすると、別のルートになります。
  2. routerWillLeave が初めて呼び出されます。私のダイアログを表示するいくつかのアクションをディスパッチします(2つのボタンが受け入れて拒否します)。
  3. acceptBtn が初めてクリックされると、routeWillLeave が再度呼び出されます (まだフックされているため)。この時点で何らかの理由で、resetForm()ディスパッチされたにもかかわらず、コンポーネントがまだ更新されていないためdirty == true、同じコード ブロックが再度実行されます。
  4. acceptBtn を 2 回クリックすると、routerWillLeave が再度トリガーされますが、今回dirty == falseは true が返され、ルートが変更されます。

最初にクリックした後にディスパッチされたアクションは次のとおりacceptBtnです。

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

これは 2 回目のクリック後です。

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 

その結果、私がやりたかったことは、acceptBtn のハンドラー関数内のフックを削除することでした。これは可能ですか?または、私が間違っていること、またはこれを達成するためのより良い方法がありますか?

4

2 に答える 2

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);
        }
      },
于 2016-03-13T04:56:02.743 に答える