在udemy教程The Complete React Developer Course中,附加包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);
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 /下一个示例with-firebase-authentication中,我看到了getInitialProps
和componentDidMount
的组合,但未能以这种方式成功实现。
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);
答案 0 :(得分:0)
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 unautorized 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 };
}