В руководстве udemy Полный курс React Developer дополнительный пакет 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 / 1014 * с аутентификацией firebase я видел комбинацию 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);