_app.tsx 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. import App, { AppContext } from "next/app";
  2. import { StoreProvider } from "easy-peasy";
  3. import Router from "next/router";
  4. import decode from "jwt-decode";
  5. import cookie from "js-cookie";
  6. import Head from "next/head";
  7. import React from "react";
  8. import { initGA, logPageView } from "../helpers/analytics";
  9. import { initializeStore } from "../store";
  10. import { TokenPayload } from "../types";
  11. import AppWrapper from "../components/AppWrapper";
  12. const isProd = process.env.NODE_ENV === "production";
  13. // TODO: types
  14. class MyApp extends App<any> {
  15. static async getInitialProps({ Component, ctx }: AppContext) {
  16. const store = initializeStore();
  17. ctx.store = store;
  18. let pageProps = {};
  19. if (Component.getInitialProps) {
  20. pageProps = await Component.getInitialProps(ctx);
  21. }
  22. const token =
  23. ctx.req && (ctx.req as any).cookies && (ctx.req as any).cookies.token;
  24. const tokenPayload: TokenPayload = token ? decode(token) : null;
  25. if (tokenPayload) {
  26. store.dispatch.auth.add(tokenPayload);
  27. }
  28. return { pageProps, tokenPayload, initialState: store.getState() };
  29. }
  30. store: ReturnType<typeof initializeStore>;
  31. constructor(props) {
  32. super(props);
  33. this.store = initializeStore(props.initialState);
  34. }
  35. componentDidMount() {
  36. const { loading, auth } = this.store.dispatch;
  37. const token = cookie.get("token");
  38. if (token) {
  39. auth.renew().catch(() => {
  40. auth.logout();
  41. });
  42. }
  43. if (isProd) {
  44. initGA();
  45. logPageView();
  46. }
  47. Router.events.on("routeChangeStart", () => loading.show());
  48. Router.events.on("routeChangeComplete", () => {
  49. loading.hide();
  50. if (isProd) {
  51. logPageView();
  52. }
  53. });
  54. Router.events.on("routeChangeError", () => loading.hide());
  55. }
  56. render() {
  57. const { Component, pageProps } = this.props;
  58. return (
  59. <>
  60. <Head>
  61. <title>
  62. {process.env.SITE_NAME} | Modern Open Source URL shortener.
  63. </title>
  64. </Head>
  65. <StoreProvider store={this.store}>
  66. <Component {...pageProps} />
  67. </StoreProvider>
  68. </>
  69. );
  70. }
  71. }
  72. export default MyApp;