2016-03-03 125 views
6

我似乎無法弄清楚如何顯示自定義對話而不是使用routeWillLeavehistory.listenBefore使用的正常window.confirm。基本上我已經建立了一個通知系統,並檢查表單是否髒const { dispatch, history, dirty } = this.props;顯示自定義對話框setRouteLeaveHook或history.listenBefore react-router/redux?

如果表單很髒,則表示用戶有未保存的更改。如果他們改變路線,我想顯示我的通知,其中將有兩個按鈕STAY,IGNORE,它們都可以採用onClick處理程序。

我花了一點時間使用Google搜索,還沒有碰到任何提及我可以如何使用routeWillLeave來完成此操作。我能找到的最接近的東西是使用history.listenBefore但是有文檔說我需要這樣做。

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

但是我使用browserHistory從反應路由器啓動我的商店const history = syncHistoryWithStore(browserHistory, store);

如何停止鏈接被點擊後的路線變化,利用我的自定義通知系統,並根據顯示的通知點擊哪個按鈕或者轉換到新路線還是停留?

下面是我的通知系統如何工作的示例以及顯然無法工作的指導方向,因爲所有返回的都是默認情況下顯示在window.confirm對話框中的字符串。

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

,我已決定採用另一種方案是在正常setRouterLeaveHook回調返回false,然後顯示我的對話框,並使用nextLocation傳遞給回調推視按鈕的下一個路由選擇。

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