Next.js Discord

Discord Forum

Rendering Server components in client

Answered
Arinji posted this in #help-forum
Open in Discord
Yo so I'm doing this infinite scroll thing which requires me to have a page with sends the initial data and render the actual data in a client component cause I need like useEffects to call my server action on reaching the end of the page



The issue is that this makes the component I want to render a client component.. I really wanna make it a server component so I can fetch data in it as well but if I do anything which is server only I get the "called in a client component so component is also client"

Any idea from y'all on this?
Answered by Ray
hmm I think it needed to be client component in this case
View full answer

31 Replies

bump :D
a page.tsx which gts initial data and then a client component which fetches on reaching the page end
but the issue is that the "Articles" which i want to render is becoming client since i import it here
the issue is that i wanna cache it and revalidate each article only with revalidateTag
Idk how to do that with the current system
oh ok i got it
Btw i tried this
making a useEffect in the article component

useEffect(() => {
SaveVar({ newsProps }).then((res) => {
setSaved(res ?? false);
});
}, []);

which calls a server action

export async function SaveVar({ newsProps }: { newsProps: NewsItemType }) {
  const saved = await unstable_cache(
    async () => {
      try {
        const isLoggedIn = cookies().get("token");

        if (!isLoggedIn) return false;
        const pb = InitPocketbase();

        pb.authStore.save(isLoggedIn.value);
        const saved = await pb
          .collection("saved")
          .getFirstListItem(`articleID = "${newsProps.id}"`);
        console.log(saved);
        if (!saved) return false;
        if (saved) return true;
      } catch (e) {
        console.log(e);
        return false;
      }
    },
    ["saved"],
    {
      tags: [`saved-${newsProps.id}`],
    }
  )();
  return saved;
}


But the revalidateTag dosent re run the useEffect + this method is really buggy
export default function Page() {

  return (
    <>
      <InfinityScrollComponent>
        <Articale />
      </InfinityScrollComponent>
    </>
  )
}


'use client'

export default function InfinityScrollComponent({children}) {
  const [data, setData] = useState([])

  return (
    <>
      ...
      {children}
      ...
    </>
  )
}
render the Articles component with children on the client component
Articles will still be a server component
thing is, article is rendered by data, lemme show
const [articles, setArticles] = useState<NewsItemType[]>(serverData);

soo i like append the new articles on this state
{articles.map((item) => {
          if (item)
            return (
              <NewsArticle category="live" key={item.id} newsProps={item} />
            );
        })}
so idk how to do the children method here
so Articles is the component which has infinity scroll?
then what component is causing "called in a client component so component is also client" error?
No, one sec
soo articles is a list of all the articles
<NewsArticle> is the component (without any actual server stuff rn) which i render with data from the article state
and you want to render NewsArticle as server component?
exacly
which i cant since for infinite scroll, anything i import in the component has to be client
hmm I think it needed to be client component in this case
Answer
yea :(
would you happen to know how i would like revalidate the component then?
revalidate the articale item?
@Ray revalidate the articale item?
yea, so i have this feature to save articles to your account
so I have this button which on click calls a server action
udh this feels wrong idk why..lemmme try this later and find out a better workaround
thanks :D
np