Skip to content

Instantly share code, notes, and snippets.

@philippetedajo
Last active August 25, 2022 12:27
Show Gist options
  • Save philippetedajo/b812ae2357c084ae16318636d582f6ae to your computer and use it in GitHub Desktop.
Save philippetedajo/b812ae2357c084ae16318636d582f6ae to your computer and use it in GitHub Desktop.
AuthContext.tsx
// ======================================= App.tsx =============================================
import App from "next/app";
import type { AppContext, AppProps } from "next/app";
import Script from "next/script";
import Router from "next/router";
import NProgress from "nprogress";
import { getIronSession } from "iron-session";
import { AuthProvider } from "../context/authContext";
import { AppLayout } from "../components";
import { sessionOptions } from "../utils/withSession";
import { UserResponse } from "../graphql/generated/graphql";
import "../styles/globals.css";
import "../public/font/stylesheet.css";
import "nprogress/nprogress.css";
interface MyAppProps extends AppProps {
user?: UserResponse;
}
function MyApp({ Component, pageProps, router, user }: MyAppProps) {
Router.events.on("routeChangeStart", () => NProgress.start());
Router.events.on("routeChangeComplete", () => NProgress.done());
Router.events.on("routeChangeError", () => NProgress.done());
return (
<AuthProvider initialUser={user}>
<AppLayout>
<Component {...pageProps} />
</AppLayout>
</AuthProvider>
</>
);
}
export default MyApp;
MyApp.getInitialProps = async (appContext: AppContext) => {
const appProps = await App.getInitialProps(appContext);
if (appContext.ctx.req && appContext.ctx.res) {
const { user } = await getIronSession(
appContext.ctx.req,
appContext.ctx.res,
sessionOptions
);
return {
...appProps,
user,
};
}
return appProps;
};
// ======================================= authContext.tsx =============================================
import React, {
createContext,
useContext,
useEffect,
useMemo,
useState,
} from "react";
import { ApolloProvider } from "@apollo/client";
import { useRouter } from "next/router";
import {
UserLoginInput,
UserResponse,
} from "../graphql/generated/graphql";
import { createApolloClient } from "../utils/client";
import axios from "axios";
interface Auth {
login: (input: UserLoginInput) => Promise<any>;
logout: () => Promise<void>;
user: any;
errors: any;
isLoading: boolean;
}
const defaultAuth = {
login: async () => {},
logout: async () => {},
user: null,
errors: null,
isLoading: false,
};
const AuthContext = createContext<Auth>(defaultAuth);
export const AuthProvider = ({
children,
initialUser,
}: {
children: React.ReactNode;
initialUser: any;
}) => {
const router = useRouter();
const [user, setUser] = useState<any>(initialUser);
const [errors, setErrors] = useState<any>(null);
const [isLoading, setIsLoading] = useState(false);
async function login(input: UserLoginInput) {
setIsLoading(true);
setUser(null);
try {
const res = await axios.post("/api/login", input);
setUser(res.data);
if (res.data.status) {
router.push("/");
}
setErrors(null);
setIsLoading(false);
return res.data;
} catch (err) {
setErrors(err);
setIsLoading(false);
return err;
}
}
async function logout() {
try {
axios.post("/api/logout").then(() => {
setUser(null);
});
router.push("/");
} catch (err) {
setErrors(err);
}
}
const value = useMemo(
() => ({ user, isLoading, errors, login, logout }),
[user, isLoading, errors]
);
return (
<AuthContext.Provider value={value}>
<ApolloProvider client={createApolloClient(user?.token)}>
{children}
</ApolloProvider>
</AuthContext.Provider>
);
};
export const useAuth = () => {
return useContext(AuthContext);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment