2016-03-03 65 views
6

普通のwindow.confirmの代わりにrouteWillLeavehistory.listenBeforeを使用する代わりに、カスタムダイアログを表示する方法がわかりません。基本的に私は通知システムを構築し、フォームが汚れていないかどうかを確認していますconst { dispatch, history, dirty } = this.props;カスタムダイアログを表示するsetRouteLeaveHookまたはhistory.listenBefore react-router/redux?

フォームが汚れていると、ユーザに未変更の変更があることを意味します。彼らがルートを変更した場合、私は通知を表示したいと思います。STAYIGNOREは、どちらもonClickハンドラを取ることができます。

Iveはグーグルで時間を費やして、routeWillLeaveを使ってどのようにこれを達成するかについての言及を見つけませんでした。私が見つけることができる最も近いものはhistory.listenBeforeを使用することでしたが、そこには私がこれを行う必要があると言われています。

let history = createHistory({ 
    getUserConfirmation(message, callback) { 
    callback(window.confirm(message)) // The default behavior 
    } 
}) 

しかし、私は、リンクがクリックされた後にルート変更を停止することができますどのようにconst history = syncHistoryWithStore(browserHistory, store);

は、私のカスタム通知システムを使用してに応じて通知を表示する私の店を開始するために反応し、ルータからbrowserHistoryを使用していますどのボタンをクリックして新しいルートに移動するか、または滞在しますか?

ここでは、通知システムがどのように動作しているのか、そして方向がわからない場合の例を示します。この戻り値はすべて、デフォルトでwindow.confirmダイアログに表示される文字列です。私が使用することを決定した別の解決策は、通常のsetRouterLeaveHookコールバックでfalseを返し、その後、私のダイアログを表示し、nextLocationを使用することです

history.listenBefore((location) => { 
    if(this.props.dirty){ 
    const acceptBtn = { 
     title: 'STAY', 
     handler: ignoreRouteChange() //This can be any function I want 
    } 
    const denyBtn = { 
     title: 'IGNORE', 
     handler: continueRouteChange() //This can be any function I want 
    } 
    return dispatch(addNotification({ 
     message: 'You have unsaved changes!', 
     type: NOTIFICATION_TYPE_WARNING, 
     duration: 0, 
     canDismiss: false, 
     acceptBtn, 
     denyBtn 
    })); 
    return "Usaved changes!" 
    } 
}); 

おかげ

+1

私はちょうどここに同様の質問に答え:http://stackoverflow.com/a/35793421/52041そのため –

+0

おかげで、ちょうどあなたがその解決策を考え出すでしたか好奇心? setRouterLeaveHookがどのように実装され、asynvバージョンを提供するためにそれを再実装したかを掘り下げましたか? – Deep

+0

いいえ、setRouterLeaveHookの動作に基づいて、ちょうど同僚と少しのブレーンストーミングを行いました。 –

答えて

0

は、ボタンに応じて、次のルートをプッシュするコールバックに渡さ選択。

router.setRouteLeaveHook(route, this.routerWillLeave.bind(this)); 

routerWillLeave(nextLocation){ 
    let { dirty, dispatch, resetForm } = this.props; 
    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(); 
      // 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); 
     } 
     }, 
     denyBtn: { 
     title: 'Deny', 
     handler: (e) => { 
      e.preventDefault(); 
      dispatch(closeDialog()); 
     } 
     } 
    } 
    dispatch(addDialogWindow(dialog)); 
    dispatch(openDialog(false, (e) => dispatch(closeDialog()), false)); 
    return false; 
    } 
    return true; 
} 
+0

'setTimeout'を使わずにまだ小道具が更新されない理由は何ですか? – Yuri

+0

ユーザーがブラウザの戻るボタンを使用して移動しようとしている場合、これは変な動作ではありません - >あなたのコードは履歴に戻るのではなく、新しい場所を履歴にプッシュしますか? – nzjoel

関連する問題