npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

react-route-guard

v1.0.7

Published

Add powerful Route Guard functionality to `react-router-dom`

Downloads

50

Readme

React Route Guard

Based on react-router-dom with route guard functionality on top of it. It makes it easier to control permissions and roles on a route.

Requirements

  • Node <=7.1

Install

yarn add react-route-guard

You don't need to install @types/react-route-guard, as it's written in TypeScript and the npm module already has index.d.ts there.

Concept

  • SecureRoute

    <SecureRoute> works like same way as <Route> and therefore you can use it in the exact same way. To enable the RouteGuard features pass in extra props (see below). SecureRoute will then perform the following tasks:

    • No DOM component will be created before <SecureRoute> has finished its check

    • When the <SecureRoute> component has mounted, it will run RouteGuard.shouldRoute(). When this function is complete, SecureRoute will update the state. RouteGuard.shouldRoute() can synchronously return a boolean or asynchronously return a Promise<boolean> or Observable<boolean>

    • SecureRoute.render() will only render the route component when route guard has finished, and will render <Redirect to={this.props.redirectToPathWhenFail | '/'} /> if the route guard check fails

    <Router>
    <Switch>
        <SecureRoute path='/about' component={AboutComponent} />
        <SecureRoute path='/users' component={UserListComponent} routeGuard={UserRouteGuard} redirectToPathWhenFail='/login' />
        <SecureRoute path='/users/:id' component={UserEditComponent} routeGuard={UserRouteGuard} redirectToPathWhenFail='/login' />
        <Route />
        <Route />
    </Switch>
    </Router>
  • RouteGuard

    RouteGuard is responsible for telling <SecureRoute> whether to enter that route or not. shouldRoute() is the key to making that happen, this method must return a boolean value in sync mode or return a Promise<boolean> or Observable<boolean> in async mode. Before the RouteGuard finished, no child components will be rendered, which means no real routing will be executed. RouteGuard will stop unauthorized users seeing a route altogether.

export type RouteGuardResultType = boolean | Promise<boolean> | Observable<boolean>

/**
* @export
* @interface RouteGuard
*/
export interface RouteGuard {
    shouldRoute: () => RouteGuardResultType
}

Usage

Here are some shouldRoute() example for different situation:

  • Sync example
shouldRoute(): RouteGuardResultType {
    // Sync API call here, and the final return value must be `map` to `boolean` if not
    const resultFromSyncApiCall = true;
    return resultFromSyncApiCall
}
  • Async Promise example
async shouldRoute(): RouteGuardResultType {
    // You can use a `Promise` to get
    // the final boolean result 
    return new Promise((resolve, reject) => {
        // Simulate call backend API for checking the authentication and even authorization
        setTimeout(() => {
            resolve(true)
        }, 3000)
    });
}
  • Async Promise example with multiple promises
async shouldRoute(): RouteGuardResultType {
    // You can use `Promise.all()` for getting
    // the final boolean result to based on multiple requirements 

    const results = await Promise.all([
        loginUserPromise,
        getUserPermissionPromise,
        getUserDashboardPromise
    ])

    return results[0].user ? true : false
}
  • Async Observable example
shouldRoute(): RouteGuardResultType {
    // If use Redux, we can dispatch an action to tell UI that `RouteGuard` is running.
    // This is useful for displaying loading indicators before the `shouldRoute` is complete
    appStore.dispatch(routingActions.executeRouteGuard())

    // Simulate a call to an API to grab the user and permissions
    return Observable.timer(1000)
        .map(n => {
            // When API call done, we need to `map` to `boolean` if not
            return true
        })
        .take(1)
        // If use Redux, then dispatch an action to tell UI that `RouteGuard` is done, can hide 
        // the loading spin right now.
        .do(() => appStore.dispatch(routingActions.executeRouteGuardDone()))
    }
  • Async real world example
shouldRoute(): RouteGuardResultType {
    appStore.dispatch(routingActions.executeRouteGuard())

    // Get the entire state to check whether the user is already logged in or not
    const appState: AppState = appStore.getState() as AppState;

    // Already logged in, pass instantly
    if (appState.auth.loginUser && (!appState.auth.loginError || appState.auth.loginError === '')) {
        // We can call any BackEnd APIs to rebuild the entire app state that are needed for the 
        // routed component to be rendered correctly
        //
        // Passed
        return true
    } else {
        // Say for instance a user just opened a URL in a new tab, then we can try to load some 
        // cookie or call some API to load user info. If the API responds successfully, 
        // then the check has passed. From here we rebuild the entire
        // app state for the routed component if needed
        
        return UserService.loadUserStateFromCookie()
            .switchMap(loadedUser => loadedUser ? UserService.loadUserList() : Observable.of(false))
            .do(userList => {
                // Dispatch an action to let Reducer rebuild the state synchronize
                if (userList && typeof(userList) === 'object') {
                    appStore.dispatch(actions.rebuildState(userList))) 
                }
            }
            // Map to boolean result
            .map(userList => userList ? true : false)
            .take(1)
    }
}