Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

177
Visualizações
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 Respostas
Responde à pergunta

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 Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda