Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

175
Views
React: Dynamic number of stateful items, AKA dealing with "Rendered more hooks than during the previous render"

I'm trying to build a tree based forum similar to reddit and hackernews. I'm using react and recoil to manage state. I'm not sure if recoil is necessary for this particular problem as the state exists within a single page, but I'm open to using it in any potential solution. I would prefer to stick with these libraries unless there is a convincing reason to branch out.

I have a useEffect hook that fetches a thread's replies.

  useEffect(() => {
    async function fetchReplies() {
      if (!router.isReady) return;
        const res = await fetchWithTimeout(
          `${process.env.NEXT_PUBLIC_API_URL}/threads/${threadId}/replies`,
          {
            headers: {
              Authorization: `Bearer ${userToken}`,
            },
            timeout: 15000,
          }
        );
        //build replies object from response here
        setReplies(myRepliesObject);
    }
    fetchReplies();
  }, [router.isReady]);

These replies are then pumped into the thread body which loops over the data to create replies.

function ThreadBody(replies: any) {
  let replyItems = [];
  for (let i = 0; i < replies.length; i++) {
    replyItems.push(ThreadReply(replies[i], 0));
  }

Like most tree based forums, I want to give users the ability to open and close particular reply trees. To do so, I gave each reply a state of isOpen.

function ThreadReply(post, level) {
  const [isOpen, setIsOpen] = useState(true);
....

This worked great when I had a static json object to mock my replies.

Trouble is, once I linked my backend and have a dynamic number of replies, I get the error Rendered more hooks than during the previous render upon setting replies.

I've tried atomFamilies, but I can't seem to figure out how I would set one (to update isOpen) with a dynamic atomFamilyId without violating the same constraint of more renders.

It seems like it'd be possible for me to clone, edit, and replace the entire replies state, but that seems insanely expensive to set a single field in what could be a thousands long list. I haven't gone down that road because I know I'll end up shipping it due to "it works" inertia.

I'm self-taught when it comes to frontend and am surely missing some seminal knowledge. Any recommendations?

about 4 years ago · Juan Pablo Isaza
1 answers
Answer question

0

I figured it out, I need to use JSX components instead of calling the functions directly. I'd love it if someone could explain exactly why, though. I also changed my components to be arrow functions, but I'm pretty sure that's unnecessary.

ThreadBody now creates ThreadReplies as so

const ThreadBody = (replies: any) => {
  let replyItems = [];
  for (let i = 0; i < replies.length; i++) {
    replyItems.push(<ThreadReply post={replies[i]} level={0} />);
  }

Thread Replies now look like this

const ThreadReply = ({ post, level }) => {
  const [isOpen, setIsOpen] = useState(true);

I spent nearly two days figuring this out, so don't feel bad if you get stuck for a few hours!

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!