History: Advanced confirming navigation with custom callback function

Created on 11 Apr 2016  Â·  2Comments  Â·  Source: ReactTraining/history

history.listenBefore assumes only string message or boolean as returning type. It would be handy if we can return a custom function that is passed down to the getUserConfirmation. That would give more control on how confirming dialog can behave:

history.listenBefore(location => {
  if (form.dirty) {
    return (cb) => {
      customDialog.show()
        .onConfirm(() => cb(true))
        .onCancel(() => cb(false))
    }
  } else {
    return true
  }
})
const history = createHistory({
  getUserConfirmation(messageOrFn, cb) {
    switch (typeof messageOrFn) {
      case 'string':
        cb(window.confirm(messageOrFn))
        break
      case 'function':
        const result = messageOrFn(cb)
        if (typeof result.then == 'function') {   // Promise
          result.then(cb).catch((err: Error) => {
            console.error('Error during routing confirmation callback: ', err, err.message)
            cb(false)
          })
        } else if (typeof result == 'boolean') {
          cb(result)
        } // else - cb should be called from inside messageOrFunction
        break;
    }
  }
})

In conjunction with react-router's routerWillLeave it should be very useful.

Most helpful comment

Can't understand what exactly is not true? Checking of string type is done right here: https://github.com/mjackson/history/blob/dbd56c44976960ba2361ba39a0f57687e3d3ea0a/modules/createHistory.js#L74

If returning type is not string getUserConfirmation is not called. I've checked this behaviour. Function is accepted, when I modify the condition this way:

if (getUserConfirmation && (typeof message === 'string' || typeof message === 'function')) {
  getUserConfirmation(message, (ok) => callback(ok !== false))
}

If it is not recommended than what is the recommended way to show custom confirmation dialogs for different cases, taking into account that getUserConfirmation is done once during react-router setup? For example in some cases I want to give three choises for the user instead of two: "Leave without saving", "Save and continue", "Cancel".

Why do we need such limitations?

All 2 comments

That's not true w/r/t the return type – check the signature on listenBefore hooks. Note this isn't recommended for confirming navigation, though, and is intentionally not exposed within the React Router API.

Can't understand what exactly is not true? Checking of string type is done right here: https://github.com/mjackson/history/blob/dbd56c44976960ba2361ba39a0f57687e3d3ea0a/modules/createHistory.js#L74

If returning type is not string getUserConfirmation is not called. I've checked this behaviour. Function is accepted, when I modify the condition this way:

if (getUserConfirmation && (typeof message === 'string' || typeof message === 'function')) {
  getUserConfirmation(message, (ok) => callback(ok !== false))
}

If it is not recommended than what is the recommended way to show custom confirmation dialogs for different cases, taking into account that getUserConfirmation is done once during react-router setup? For example in some cases I want to give three choises for the user instead of two: "Leave without saving", "Save and continue", "Cancel".

Why do we need such limitations?

Was this page helpful?
0 / 5 - 0 ratings