Next.js Discord

Discord Forum

Error when calling router.push from a callback after calling fetch?

Unanswered
Jumbo flying squid posted this in #help-forum
Open in Discord
Jumbo flying squidOP
Laying the groundwork/context:

I have a project with the following structure:

/app
/app/(user-provider)

with the following layout file:
/app/(user-provider)/layout.js
export default async function Layout({ children }) {
  const user = await getUserFromCookies();

  return <UserProvider sessionUser={user}>{children}</UserProvider>;
}


under that layout there are two folders dividing the app:

/app/(user-provider)/(auth) with the layout file:
/app/(user-provider)/(auth)/layout.js
export default function Layout({ children }) {
  const { user } = useUser();
  const pathname = usePathname();

  // Track mounted state to prevent running auth page transitions on first visit
  const [mounted, setMounted] = useState(false);
  useEffect(() => {
    setMounted(true);
  }, []);

  if (!!user) return redirect("/dashboard");
  return (
    <div className="h-screen  w-screen">
      <div>
      // branding stuff
      </div>
      <div>
        <AnimatePresence initial={mounted}>{children}</AnimatePresence>
      </div>
    </div>
  );
}


/app/(user-provider)/(protected) with the layout file:
/app/(user-provider)/(protected)/layout.js
export default function Layout({ children }) {
  const { user } = useUser();

  if (!user) return redirect("/login");
  return <>{children}</>;
}


my issue is that when calling router.push from a page in one route group (auth/protected) to the other route group after calling fetch / a hook like set state I get the following errors:

Cannot update a component (`HotReload`) while rendering a different component (`Router`).


and

Uncaught Error: Rendered more hooks than during the previous render.


For some examples of what I mean when I say "after calling a hook or fetch":

3 Replies

Jumbo flying squidOP
post continued with examples:

/app/(user-provider)/(protected)/example/page.js

// This does works
  const resetUserAsync = useCallback(async () => {
    resetUser();
  }, [resetUser]);

  const goSomewhere = () => {
    resetUserAsync().then(() => push("/login"));
  };

// This does not work 
  const goSomewhere = () => {
    resetUser();
    push("/login");
  };

// This does not work
  const resetUserAsync = useCallback(async () => {
    const response = await fetch("/api/ping"); // arbitrary endpoint, returns status 200 with body "pong"
    const data = await response.data;
    console.log(data);
    if (response.ok) {
      resetUser();
    }
    return true;
  }, [resetUser]);

  const goSomewhere = () => {
    resetUserAsync().then(() => push("/login"));
  };


Note that /login is defined in the file /app/(user-provider)/(auth)/login/page.js and is therefor under the other route group than the example file.

Any idea's what I'm doing wrong or what's causing this?
Jumbo flying squidOP
additionally resetUser is just a wrapper around setUser(null) in the UserContext
Jumbo flying squidOP
As a work around In case anyone else runs into this I have replaced any call to router.push that was giving problems with setting the newly created state shouldPushToDestination to true, triggering a useEffect which calls router.push("/destination").