reactjsreact-hooksdiscord

React Use state run twice


I'm trying to run my Setup function once when the Discord Activity loads (https://discord.com/developers/docs/activities/how-activities-work).

My code somehow runs the function twice and creates an error.

console errors

Here is the code I'm using:

function App() {
  const [auth, setAuth] = useState<authType>(null);

  async function setupDiscordSdk() {
    const CLIENT_ID = "my client id";
    const discordSdk = new DiscordSDK(CLIENT_ID, { disableConsoleLogOverride: true });
    await discordSdk.ready();
    console.warn('DISCORD SDK READY!') // This somehow calls twice

    // Authorize with Discord Client
    const { code } = await discordSdk.commands.authorize({
      client_id: CLIENT_ID,
      response_type: "code",
      state: "",
      prompt: "none",
      scope: [
        "identify",
      ],
    });

    // Retrieve an access_token from your activity's server
    const response = await fetch("/api/token", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        code,
      }),
    });

    const { access_token, publicProfile, authkey } = await response.json();
    localStorage.setItem('bread:authkey', authkey);

    // Authenticate with Discord client (using the access_token)
    let auth = (await discordSdk.commands.authenticate({
      access_token,
    }) as authTypeNOTNULL);

    auth.publicProfile = publicProfile as boolean;
    auth.user.avatarURL = (auth.user.avatar ? `https://cdn.discordapp.com/avatars/${auth.user.id}/${auth.user.avatar}.png?size=256` : `https://cdn.discordapp.com/embed/avatars/${(BigInt(auth.user.id) >> 22n) % 6n}.png`);
    auth.discordSdk = discordSdk;
    setAuth(auth);
    console.warn('AUTHED SUCCESSFULLY.');
  };

  async function openLink(url: string) {
    console.warn('Trying to open URL', url);
    console.log(auth)
    if (!auth) return console.error('Not authed');
    return await auth.discordSdk.commands.openExternalLink({ url });
  };

  useEffect(() => console.log(auth), [auth]);

  useEffect(() => {
    setupDiscordSdk().catch(console.error);
  }, [])

  return (
    <>
      ...
    </>
  )
}

export default App;

Everything else works, just that auth does not. Can anyone please help me?

Thanks in advance.


Solution

  • I fixed it with the help of comments and by myself. Here is my updated code:

    function App() {
      const [auth, setAuth] = useState<authType>(null);
      const [isAuthing, setIsAuthing] = useState(false);
      const [showLeaderboard, setShowLeaderboard] = useState(false);
      const hasInitialized = useRef(false);
    
      async function setupDiscordSdk() {
        console.warn('Trying to login');
        if (isAuthing) return;
        setIsAuthing(true);
    
        const CLIENT_ID = "1170963763340517466";
        const discordSdk = new DiscordSDK(CLIENT_ID, { disableConsoleLogOverride: true });
        await discordSdk.ready();
        console.warn('DISCORD SDK READY!')
    
        // ...
    
        setAuth(authing);
        console.warn('AUTHED SUCCESSFULLY.');
        setIsAuthing(false);
      }
    
      useEffect(() => {
        if (!hasInitialized.current) {
          setupDiscordSdk();
          hasInitialized.current = true;
        }
      }, []);