https://supertokens.com/ logo
Title
c

Chunkygoo

12/16/2022, 7:31 AM
I followed the Next.js set up and I'm getting "Google Provider was already initialized" in the console. Is that expected?
r

rp

12/16/2022, 7:32 AM
hey @Chunkygoo
this means you are calling google.init twice - i think.. can i have more details?
c

Chunkygoo

12/16/2022, 7:33 AM
import type { Request, Response } from "express";
import type { NextApiRequest, NextApiResponse } from "next";
import NextCors from "nextjs-cors";
import supertokens from "supertokens-node";
import { middleware } from "supertokens-node/framework/express";
import { superTokensNextWrapper } from "supertokens-node/nextjs";
import { backendConfig } from "../../../config/backendConfig";
import { env } from "../../../env/server.mjs";

supertokens.init(backendConfig());

export default async function superTokens(
  req: NextApiRequest & Request,
  res: NextApiResponse & Response
) {
  // NOTE: We need CORS only if we are querying the APIs from a different origin
  await NextCors(req, res, {
    methods: ["GET", "HEAD", "PUT", "PATCH", "POST", "DELETE"],
    origin: env.APP_URL,
    credentials: true,
    allowedHeaders: ["content-type", ...supertokens.getAllCORSHeaders()],
  });

  await superTokensNextWrapper(
    async (next) => {
      res.setHeader(
        "Cache-Control",
        "no-cache, no-store, max-age=0, must-revalidate"
      );
      await middleware()(req, res, next);
    },
    req,
    res
  );
  if (!res.writableEnded) {
    res.status(404).send("Not found");
  }
}
This is in src/pages/api/auth/[[...path]].ts
In _app.tsx:
if (typeof window !== "undefined") {
  // we only want to call this init function on the frontend, so we check typeof window !== 'undefined'
  SuperTokensReact.init(frontendConfig);
}
r

rp

12/16/2022, 8:14 AM
this seems fine
can i see a screenshot of the error message?
c

Chunkygoo

12/16/2022, 8:04 PM
It's literally just that message
"Google Provider was already initialized"
r

rp

12/17/2022, 4:06 AM
Hmmm. I don’t think we print this message out from anywhere in supertokens.
So please check if it’s coming from somewhere else
c

Chunkygoo

12/18/2022, 6:16 AM
Nope I code searched it and I'm not using it anywhere
and ST is the only library using my google oauth ID
Since the line "supertokens.init(backendConfig());" is in the api/ directory
wouldnt that get triggered everytime?
r

rp

12/18/2022, 11:17 AM
Hmm. @nkshah2 can help here tomorrow
c

Chunkygoo

12/18/2022, 7:06 PM
Thanks @rp
n

nkshah2

12/19/2022, 5:12 AM
Hey @Chunkygoo , can you use
npx create-supertokens-app@latest
and choose NextJS to see if this issue can be replicated there?
The log you are seeing comes from calling Google.init multiple times on the frontend
If the snippet you sent is the only instance of calling
SuperTokensReact.init
then I would double check if that is being executed multiple times
c

Chunkygoo

12/19/2022, 5:15 AM
So this line is in _app.tsx
if (typeof window !== "undefined") {
  // we only want to call this init function on the frontend, so we check typeof window !== 'undefined'
  SuperTokensReact.init(frontendConfig);
}
And _app.tsx gets mounted once but gets rerendered when the route changes
frontendConfig contains the object that calles Google.init()
n

nkshah2

12/19/2022, 5:18 AM
Right so you would want that code to run only once,
useEffect
by default runs on client side so you could use that. As a side note, the log isnt an error and wont cause any side effects
c

Chunkygoo

12/19/2022, 10:30 PM
Thanks
I changed my frontendConfid from an object to a function that returns an object and it solved the issue. Do you know why?
n

nkshah2

12/20/2022, 4:21 AM
Are you calling it like this?
SuperTokensReact.init(frontendConfig());
c

Chunkygoo

12/21/2022, 5:08 AM
Yes
now I am
before I was doing SuperTokensReact.init(frontendConfig) and frontendConfig was just an object rather than a function that returns an object
n

nkshah2

12/21/2022, 5:09 AM
Hmm strange, don’t know why that would fix this for you but at least it’s good to know
c

Chunkygoo

12/21/2022, 5:10 AM
Only reason I could think of is init checks if it's previously init'ed. If not, run frontendConfig() which would return the object that contains Google.init()". But because I was previously passing in an object which would result in Google.init() always getting called?
n

nkshah2

12/21/2022, 5:13 AM
Well in this case it wouldn’t be init that’s checking anything because regardless of how many times it runs it always gets an object passed to it (since you’re calling the function, the result is what’s passed to init and not the function itself)
This may be an optimisation baked into Next?
c

Chunkygoo

12/21/2022, 5:21 AM
Im not sure
What I meant as init keeps track of a variable like isInit = true/false
and it receives an agument
argument
and some pseudologic
n

nkshah2

12/21/2022, 5:23 AM
Init does keep track of whether it was called for a page load, but using a function or an object doesnt make a difference
c

Chunkygoo

12/21/2022, 5:23 AM
if isInit: dont run argument; else: run argument
yeah
I agree
Im just imagining that
there might be some optimization done somewhere
so for example
n

nkshah2

12/21/2022, 5:23 AM
So it definitely does not accept a function
That would throw an error
c

Chunkygoo

12/21/2022, 5:24 AM
ok
im not sure why
n

nkshah2

12/21/2022, 5:24 AM
Yeah, chalk it up to one of the oddities of programming :p
c

Chunkygoo

12/21/2022, 5:24 AM
xD
I think I found the reason
I just tried it again
And I confirmed that it's indeed the difference between frontendConfig() and frontendConfig that's causing the issue
I also noticed that the message "Google was already initialized" gets printed out everytime there is a [Fast Refresh]
n

nkshah2

12/21/2022, 5:31 AM
Oh like Hot Reload or something?
c

Chunkygoo

12/21/2022, 5:31 AM
The difference, I think, is buildtime vs runtime
yes
n

nkshah2

12/21/2022, 5:31 AM
Yep that would make sense
c

Chunkygoo

12/21/2022, 5:32 AM
even with frontendConfig() the hot reload still happens
but I think it doesn't call the function again
n

nkshah2

12/21/2022, 5:32 AM
Yep but hot reload is probably optimised around functions and objects
Which makes sense from a state management perspective too
c

Chunkygoo

12/21/2022, 5:32 AM
It remembers its previous value and doesnt call it again since nothing has changed
but if we pass it, frontendconfig, it simply loads it
and since google was initialized before
it shows the message
n

nkshah2

12/21/2022, 5:33 AM
Yeah this is definitely good to know
Thanks!
c

Chunkygoo

12/21/2022, 5:33 AM
Thank you too