2016-03-03 8 views
6

Non riesco a capire come mostrare un dialogo personalizzato invece di utilizzare il normale window.confirm utilizzato da routeWillLeave e history.listenBefore. Fondamentalmente ho costruito un sistema di notifica e controllo se un modulo è sporco const { dispatch, history, dirty } = this.props;Mostra finestra di dialogo personalizzata setRouteLeaveHook o history.listenPrima di reagire-router/redux?

se il modulo è sporco significa che l'utente ha modifiche non salvate. Se cambiano rotta, vorrei mostrare la mia notifica che avrà due pulsanti STAY, IGNORE che possono entrambi assumere un gestore onClick.

Ive ha trascorso un po 'di tempo su google e non ha trovato alcun riferimento a come avrei potuto ottenere ciò utilizzando routeWillLeave. La cosa più vicina che ho trovato era usare history.listenBefore tuttavia i documenti dicono che ho bisogno di farlo.

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

Ma io sto usando browserHistory da reagire-router di avviare il mio negozio const history = syncHistoryWithStore(browserHistory, store);

Come posso fermare un cambiamento percorso dopo un link è stato cliccato, mostrano una notifica utilizzando il mio sistema di notifica personalizzato e seconda su quale pulsante si fa clic su una transizione alla nuova rotta o si rimane?

Ecco un esempio di come funziona il mio sistema di notifica e la direzione in cui ovviamente non funziona perché tutto ciò che restituisce è una stringa da mostrare nel dialogo window.confirm per impostazione predefinita.

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!" 
    } 
}); 

Grazie

+1

ho solo risposto a una domanda simile qui: http://stackoverflow.com/a/35793421/52041 –

+0

Grazie per questo, solo per curiosità come ti è venuta con questa soluzione? Hai approfondito come è stato implementato setRouterLeaveHook e lo hai implementato di nuovo per fornire una versione asynv o ..? – Deep

+0

No, ho appena fatto un po 'di brainstorming con un collega, basato sul comportamento di setRouterLeaveHook. –

risposta

0

Un'altra soluzione che ho deciso di utilizzare è quello di restituire false nel normale callback setRouterLeaveHook e poi mostrare la mia finestra e utilizzare il nextLocation passato al callback per spingere il percorso successivo a seconda del pulsante selezione.

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

Qualche idea sul perché gli oggetti di scena non siano ancora stati aggiornati senza usare 'setTimeout'? – Yuri

+0

Nel caso in cui un utente stia cercando di allontanarsi usando il pulsante indietro del browser, questo non si comporterebbe in modo strano -> Il tuo codice spingerebbe una nuova posizione nella cronologia invece di tornare indietro nella cronologia? – nzjoel

Problemi correlati