如何在next.js中针对受限页面重定向到登录页面?

9
在Udemy教程《完整的React开发者课程》中,使用了额外的包history来获取路由器以在用户未经身份验证时进行重定向。其中,《完整的React开发者课程》history均为链接。
/* AppRouter.js */
import createHistory from "history/createBrowserHistory";

const AppRouter = () => (
    <Router history={history}>
      <div>
        <Switch>
            <PublicRoute path="/" component={LoginPage} exact={true} />
            <PrivateRoute
                path="/dashboard"
                component={ExpenseDashboardPage}
            />
            <PrivateRoute path="/create" component={AddExpensePage} />
            <PrivateRoute path="/edit/:id" component={EditExpensePage} />
            <Route component={NotFoundPage} />
        </Switch>
      </div>
    </Router>
);

export default AppRouter;



/* PrivateRouter.js */
import React from "react";
import { connect } from "react-redux";
import { Route, Redirect } from "react-router-dom";
import Header from "../components/Header";

export const PrivateRoute = ({
    isAuthenticated,
    component: Component,
    ...rest
}) => (
    <Route
        {...rest}
        component={(props) =>
            isAuthenticated ? (
                <div>
                    <Header />
                    <Component {...props} />
                </div>
            ) : (
                <Redirect to="/" />
            )
        }
    />
);

const mapStateToProps = (state) => ({
    isAuthenticated: !!state.auth.uid
});

export default connect(mapStateToProps)(PrivateRoute);
< p > app.js 的代码如下:

/* app.js */
import AppRouter, { history } from "./routers/AppRouter";

const store = configureStore();

const jsx = (
    <Provider store={store}>
        <AppRouter />
    </Provider>
);

firebase.auth().onAuthStateChanged((user) => {
    if (user) {
        store.dispatch(login(user.uid));
        store.dispatch(startSetExpenses()).then(() => {
            if (history.location.pathname === "/") {
                history.push("/dashboard");
            }
        });
    } else {
        store.dispatch(logout());
        history.push("/");
    }
});

ReactDOM.render(jsx, document.getElementById("app"));

我的问题是,我如何在我的Next.js项目中实现这一点?我已经尝试了类似的方式在_app.js文件中。我能否通过getInitialProps例程以某种方式实现此行为?在zeit/next示例with-firebase-authentication中,我看到了getInitialPropscomponentDidMount的组合,但没有成功地按照这种方式实现它。
import withRedux from 'next-redux-wrapper';
import App from 'next/app';
import React from 'react';
import { Provider } from 'react-redux';
import { firebase } from '../src/firebase/firebase';
import reduxStore from '../src/redux/store';

class MyApp extends App {
  static async getInitialProps({ Component, ctx }) {
    firebase.auth().onAuthStateChanged((user) => {
      if (user) {
        console.log('log in');
      } else {
        if (ctx.isServer && ctx.req.url !== '/login') {
          ctx.res.writeHead(302, { Location: '/login' });
          ctx.res.end();
        }
        console.log('log out');
      }
    });

    return {
      pageProps: Component.getInitialProps
        ? await Component.getInitialProps(ctx)
        : {}
    };
  }

  render() {
    const { Component, pageProps, store } = this.props;

    return (
      <Provider store={store}>
        <Component {...pageProps} />
      </Provider>
    );
  }
}

// firebase.auth().onAuthStateChanged((user) => {
//   if (user) {
//     console.log('log in');
//   } else {
//     // router instance not accessible!
//     Router.push("/login");
//     console.log('log out');
//   }
// });

export default withRedux(reduxStore, { debug: false })(MyApp);
1个回答

14
import Router from "next/router";

export function redirectUser(ctx, location) {
  if (ctx.req) {
    ctx.res.writeHead(302, { Location: location });
    ctx.res.end();
  } else {
    Router.push(location);
  }
}

class MyApp extends App {
  static async getInitialProps({ Component, ctx }) {
    const { token } = parseCookies(ctx);

    let pageProps = {};

    if (Component.getInitialProps) {
      pageProps = await Component.getInitialProps(ctx);
    }

    // Restrict unauthorized user
    if (!token) {
      const isProtectedRoute =
        ctx.pathname === "/account" || ctx.pathname === "/create";

      if (isProtectedRoute) {
        redirectUser(ctx, "/signin");
      }
    }
    else {
      try {
         // Restrict user based on role on certain page
        const user;
        const isRoot = user.role === "root";
        const isAdmin = user.role === "admin";
        const isNotPermitted =
          !(isRoot || isAdmin) && ctx.pathname === "/create";

        if (isNotPermitted) {
          redirectUser(ctx, "/");
        }

        pageProps.user = user;
      }
      catch (err) {
        console.error("Error getting current user", err);

        destroyCookie(ctx, "token");
        redirectUser(ctx, "/signin");
      }
    }

    return { ...pageProps };
  }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接