question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

action to prevent transition from current route

See original GitHub issue

action for use of history.block api so that user can lock or free current route. Possible use cases are unsaved forms, pending results etc.

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:28 (15 by maintainers)

github_iconTop GitHub Comments

5reactions
faceyspaceycommented, Sep 6, 2017

This is done. It’s in the @next dist-tag on npm. to get it do:

yarn upgrade redux-first-router@next

Here’s how you use it:

const routesMap = {
   HOME: '/'
   FOO: {
      path: '/foo',
      confirmLeave: (state, action) => {
         if (!state.formComplete && action.type === 'HOME' ) {
             return 'Are you sure you want to leave without completing your purchase?'
         }
     }
  }
}

So each route can have a confirmLeave option, and if you return a string it will be shown in the confirm yes|no dialog. If you return a falsy value such as undefined, the user will be able to navigate away from the current route without being shown any dialog.

If you’d like to customize that dialog (which is required in React Native since there is no window.confirm in React Native), you can pass a displayConfirmLeave option to connectRoutes like so:

const options = {
  displayConfirmLeave: (message, callback) => {
    showModalConfirmationUI({
       message,
       stay: () => callback(false),
       leave: () => callback(true)
    })
  }
}

connectRoutes(history, routesMap, options)

so showModalConfirmationUI is an example of a function you can make to display a confirmation modal. If the user presses OK call the callback with true to proceed with navigating to the the route the user was going to. And pass false to block the user.

One special thing to note is that if you define this function in the same scope that is likely created below, you can use store.dispatch to trigger showing the modal instead. You could even do:

store.dispatch({ type: 'SHOW_BLOCK_NAVIGATION_MODAL', payload: { callback } })

and then grab the callback in your <Modal /> component. Since this is happening solely on the client and the store will never need to serialize that callback (as you do when rehydrating from the server), this is a fine pattern. Redux store state can contain functions, components, etc, if you choose. The result in this case is something highly idiomatic when it comes to how you render the React component corresponding to the modal. No imperative tricks required.

Here’s a final example:

src/reducers/blockNavigation.js:

export default (state = {}, action = {}) => {
  switch (type): {
    case 'SHOW_BLOCK_NAVIGATION_MODAL':
       const { message, canLeave } = action.payload
       return { message, canLeave  }
    case 'HIDE_BLOCK_NAVIGATION_MODEL':
       return {}
    default:
       return state
  }
}

src/components/BlockModal.js:

const BlockModal = ({ show, message, cancel, ok }) =>
  !show 
    ? null
    : <div className={styles.modal}>
        <h1>{message}</h1>

        <div className={styles.modalFooter}>
               <span onClick={cancel}>CANCEL</span>
               <span onClick{ok}>OK</span>
        </div>
   </div>

const mapState = ({ blockNavigation: { message, canLeave } }) => ({
   show: !!message,
   message,
   cancel: () => canLeave(false),
   ok: () => canLeave(true)
})

export default connect(mapState)(BlockModal)

obviously you could wrap <BlockModal /> in a transition-group to create a nice fadeIn/Out animation

src/components/App.js

export default () =>
   <div>
       <OtherStuff />
       <BlockModal />
   </div>

src/configureStore.js:

const routesMap = {
   HOME: '/'
   FOO: {
      path: '/foo',
      confirmLeave: (state, action) => {
         if (!state.formComplete && action.type === 'HOME' ) {
             return 'Are you sure you want to leave without completing your purchase?'
         }
     }
  }
}

const options = {
  displayConfirmLeave: (message, callback) => {
     const canLeave = can => {
        store.dispatch({ type: 'HIDE_BLOCK_NAVIGATION_MODEL' }) // hide modal
        return callback(can) // navigate to next route or stay where ur at
     }

     store.dispatch({ 
       type: 'SHOW_BLOCK_NAVIGATION_MODAL',
       payload: { message, canLeave } 
     })
  }
}

const { reducer, middleware, enhancer } = connectRoutes(history, routesMap, options)

const rootReducer = combineReducers({ ...reducers, location: reducer })
const middlewares = applyMiddleware(middleware)
const enhancers = composeEnhancers(enhancer, middlewares)
const store = createStore(rootReducer, preLoadedState, enhancers)
3reactions
faceyspaceycommented, Jan 20, 2018

when rudy 0.0.1 is out we’ll need a few long-time users to migrate their codebases, so we can iron out kinks as fast as possible 😃

Other things we need:

  • typescript definitions
  • website!
  • demos (TodoMVC demo, blog demo, obvservables demo, sagas demo)

ps. almost almost there

Read more comments on GitHub >

github_iconTop Results From Across the Web

Preventing and Retrying Transitions - Routing - Ember Guides
When a transition is attempted, whether via <LinkTo /> , transitionTo , or a URL change, a routeWillChange event is fired on the...
Read more >
How to prevent route change using react-router - Stack Overflow
It is too late but according to the React Router Documentation you can use preventing transition with helping of <prompt> component.
Read more >
Exclude some Routes from transition. · Issue #365 - GitHub
Rendering only routes if current route is /profile . This will prevent exiting animation of any previous route and entering animation of the ......
Read more >
Route transition animations - Angular
When a user navigates from one route to another, the Angular router maps the URL path to a relevant component and displays its...
Read more >
Animating Angular Route Transitions - DEV Community ‍ ‍
During a transition, a new view is inserted directly after the old one and both elements appear on screen at the same time....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found