Next.js Discord

Discord Forum

Can't use React.useEffect() in a Client Component imported by server.

Answered
White-winged Scoter posted this in #help-forum
Open in Discord
White-winged ScoterOP
Greetings!

For some odd reason, whenever I have a client component that is imported by the server, the useEffect() hook will never fire, although other hooks work. So if anyone knows what I'm doing wrong, or can explain this I'd much appreciate it. (UseEffect seems to only work when the Component isn't called, but rahter rendered as an entire page.)


Here's my code:

/* My Page.tsx (server) */

import { ModeToggle } from "@/components/theme-toggle";
import MobileBar from "./MobileBar/MobileBar";

export default function Home() {
  return (
    <>

{/* MOBILE BAR IS THE CLIENT COMPONENENT */}
    <MobileBar/>
    </>
  );
}


And here is the Mobile Bar (messy ik)
"use client"
import { ArrowUpIcon, MagnifyingGlassIcon } from "@radix-ui/react-icons";
import { Button } from "@/components/ui/button";
import { isMobile } from "react-device-detect";
import { useEffect, useState } from "react";
import { usePathname, useSearchParams } from 'next/navigation'

export default function MobileBar() {
/* Deleted other hooks and funcs so I can fit this msg in 2,000 chars */
    useEffect(() => {
        console.log("use Effect ran?") // Never Runs
        if (window.screen.width < 640) {
            setMobileScreen(true)
        } else if (window.screen.width >= 640) {
            setMobileScreen(false)
        }

        if (isMobile || mobileScreen) {
            window.addEventListener("scroll", handleScroll, { passive: true });
            return () => {
                window.removeEventListener("scroll", handleScroll);
            };
        }
    })

    return (
         {/*Deleted JSX so I can fit this message in 2,000 chars*/}  
    )
}


Let me know if you see the issue or can explain to me why this is. Much appreciated!
Answered by White-winged Scoter
So apparently the Client Component will not go render on the Client if it's Rendered with components which run on the server, or use some sort of Server context.
View full answer

18 Replies

Giant panda
Your effect has neither a dependency array, nor is it returning something along all codepaths. You should fix that first.
White-winged ScoterOP
Alright
useEffect(() => {
        console.log("use Effect ran?")
        if (window.screen.width < 640) {
            setMobileScreen(true)
            return () => {
                setMobileScreen(true);
            }
        } else if (window.screen.width >= 640) {
            setMobileScreen(false)
            return () => {
                setMobileScreen(false);
            }
        }

        if (isMobile || mobileScreen) {
            window.addEventListener("scroll", handleScroll, { passive: true });
            return () => {
                window.removeEventListener("scroll", handleScroll);
            };
        }
    }, [mobileScreen, isMobile])
White-winged ScoterOP
I figured it out!
Basically, it wasn't how my useEffect was written, but it was something else
White-winged ScoterOP
So apparently the Client Component will not go render on the Client if it's Rendered with components which run on the server, or use some sort of Server context.
Answer
White-winged ScoterOP
So

This will work:
// Page.tsx
"use server"
import ClientComponent from "@/app/..."

export default async function Home() {
  return (
    <>
     <ClientComponent/>
    </>
  )
}


This will work
// Page.tsx
"use server"
import ClientComponent from "@/app/..."
import ClientComponent2 from "@/app/..."

export default async function Home() {
  return (
    <>
     <ClientComponent/>
     <ClientComponent2/>
    </>
  )
}
However
This won't work:
// Page.tsx
"use server"
import ClientComponent from "@/app/..."
import ServerComponent from "@/app/..."
export default async function Home() {
  return (
    <>
     <ClientComponent/>
     <ServerComponent/>
    </>
  )
}


Neither will this
// Page.tsx
"use server"
import ClientComponent from "@/app/..."
import ClientComponent_ from "@/app/..." // A client component with "use client", that imports and uses any type, variable, function, etc from a script that uses server context
export default async function Home() {
  return (
    <>
     <ClientComponent/>
     <ServerComponent/>
    </>
  )
}
Giant panda
Probably because you wrongly use use server
White-winged ScoterOP
So I guess that's something you guys should really put on the Documentation...
Giant panda
You have to remove it from pages
@Giant panda Probably because you wrongly use `use server`
White-winged ScoterOP
Yea Ik, I put use server there just to show case that it's server context.
Giant panda
It's highly irritating because it's not just a comment, it changes how files are handled
If you can reproduce the issue in a fresh project using a sandbox or a simple reproduction repository you could link it for others to confirm the issue