_app.tsx 2.2 KB

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