Search code examples
javascripthtmlreactjssupabase

Why am I getting "Uncaught DOMException: failed to execute add on DOMTokenList"


I am getting this error for some reasonenter image description here And this one => enter image description here

I believe this error has something to do with my changing the mode from light mode to dark mode. Here is what that function looks like in my navbar.jsx => "

// function to toggle between dark mode / light
  const toggleTheme = () => {
    setTheme((prevTheme) => (prevTheme === "light" ? "dark" : "light"));
  };"


   <div id="navbar-container" className={`flex justify-between z-10 items-center top-0 pt-3 px-4 w-full sticky ${theme === "dark" ? "bg-slate-950": "bg-white"}`}>

Here is my App.jsx where the themeprovider is located (I use shadcn-ui for the themeprovider) =>

const Navigation = () => {
  const location = useLocation();
  const loginRoute = location.pathname === '/login';
  const emailConfirmRoute = location.pathname === "/success/confirm";

  // Determine which component to render based on the route
  const renderNavbar = loginRoute || emailConfirmRoute ? null : (location.pathname === '/' ? <Navbar /> : <DashboardNavbar />);
  

  return renderNavbar;
};

const FooterComponent = () => {
  const location = useLocation();
  const loginRoute = location.pathname === '/login';

  const renderFooter = loginRoute ? null : (location.pathname === '/' ? <Footer /> : null);
  
  return renderFooter;
};

// Create context for the user
export const UserContext = createContext(null);

// Custom hook to use the user context
export const useUser = () => useContext(UserContext);

const App = () => {
  const [user, setUser] = useState(null);

  // useEffect for auth to determine if user is authenticated or not
  useEffect(() => {
    // Define an async function to get the session
    async function getSession() {
      try {
        // Wait for the session promise to resolve
        const {data: { session }} = await supabase.auth.getSession()
  
        // If there is a session, set the user state to the session's user information
        if (session) {
          console.log("Session object:", session);
        
        if (session.user && session.user.aud) {
          console.log("Session aud:", session.user?.aud)
        } else {
          console.log("Session is undefined")
        }
        setUser(session.user);
        
      } else {
          console.log('No active session: User is not logged in');
        }
      } catch (error) {
        console.error('Error fetching session:', error);
      }
    }
    // Call the async function
    getSession();
  }, [setUser]);

  return (
    <ThemeProvider defaultTheme='light' storageKey='vite-ui-theme'>
      <UserContext.Provider value={{ user, setUser }}>
        <Router>
          <div>
            {/* Render the appropriate component based on the route */}
            <Navigation/>
            <Routes>
              <Route path="/" element={<Home />} />
              <Route path='/create' element={<Dashboard />} />
              <Route path='/login' element={<Login />} />
              <Route path='/success/confirm' element={<ConfirmEmail />} />
            </Routes>
            <FooterComponent />
          </div>
        </Router>
      </UserContext.Provider>
    </ThemeProvider>
  );
};

export default App;"

And the themeprovider.jsx =>

/* eslint-disable react/prop-types */
import { createContext, useContext, useEffect, useState } from "react";

const ThemeProviderContext = createContext(null);

export function ThemeProvider({
  children,
  defaultTheme = "system",
  storageKey = "vite-ui-theme",
  ...props
}) {
  const [theme, setTheme] = useState(
    () => localStorage.getItem(storageKey) || defaultTheme
  );

  useEffect(() => {
    const root = window.document.documentElement;

    root.classList.remove("light", "dark");

    if (theme === "system") {
      const systemTheme = window.matchMedia("(prefers-color-scheme: dark)")
        .matches
        ? "dark"
        : "light";

      root.classList.add(systemTheme);
      return;
    }

    root.classList.add(theme);
  }, [theme]);

  const value = {
    theme,
    setTheme: (theme) => {
      localStorage.setItem(storageKey, theme);
      setTheme(theme);
    },
  };

  return (
    <ThemeProviderContext.Provider {...props} value={value}>
      {children}
    </ThemeProviderContext.Provider>
  );
}

// eslint-disable-next-line react-refresh/only-export-components
export const useTheme = () => {
  const context = useContext(ThemeProviderContext);

  if (context === undefined)
    throw new Error("useTheme must be used within a ThemeProvider");

  return context;
};

Now the weird part => This error only happens when I am logged in on my app which uses supabase for authentication. For example when I clear my browser cahce or check out the app in icognito, everything works as expected including changing from light to dark theme and vice versa. This means that something is going on with my authentication that is causing this error.

Any help would be much appreciated. Genuinly don't know where to look to figure this out.


Solution

  •   const toggleTheme = () => {
        // wrong you're passing a function instead of a string to set state of the theme
        setTheme((prevTheme) => (prevTheme === "light" ? "dark" : "light"));
      };"
    

    so you're using the useState hook to invoke setTheme function and set the value, the argument to set should be a string. judging by how you set the defaultTheme in ThemeProvider Component as "light"

    in your code you're passing an arrow function to setTheme hook, which is not what the ThemeProvider expected.

    replace it with

    ...
    setTheme(prevTheme === 'light' ? 'dark' : 'light');
    ...