Как перенаправить на страницу входа для запрещенных страниц в next.js? - PullRequest
0 голосов
/ 20 октября 2019

В руководстве 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);
...