Estoy tratando de construir un foro basado en un árbol similar a reddit y hackernews. Estoy usando reaccionar y retroceder para administrar el estado. No estoy seguro de si el retroceso es necesario para este problema en particular, ya que el estado existe dentro de una sola página, pero estoy abierto a usarlo en cualquier solución potencial. Preferiría quedarme con estas bibliotecas a menos que haya una razón convincente para expandirme.
Tengo un gancho useEffect que obtiene las respuestas de un hilo.
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]);Estas respuestas luego se bombean al cuerpo del hilo que recorre los datos para crear respuestas.
function ThreadBody(replies: any) { let replyItems = []; for (let i = 0; i < replies.length; i++) { replyItems.push(ThreadReply(replies[i], 0)); }Como la mayoría de los foros basados en árboles, quiero dar a los usuarios la capacidad de abrir y cerrar árboles de respuestas particulares. Para hacerlo, le di a cada respuesta un estado de isOpen.
function ThreadReply(post, level) { const [isOpen, setIsOpen] = useState(true); ....Esto funcionó muy bien cuando tenía un objeto json estático para burlarse de mis respuestas.
El problema es que, una vez que vinculé mi backend y obtuve un número dinámico de respuestas, aparece el error Rendered more hooks than during the previous render al configurar las respuestas.
Probé atomFamilies , pero parece que no puedo entender cómo configuraría uno (para actualizar isOpen) con un atomFamilyId dinámico sin violar la misma restricción de más renderizados.
Parece que sería posible para mí clonar, editar y reemplazar todo el estado de las respuestas, pero parece increíblemente costoso establecer un solo campo en lo que podría ser una lista larga de miles. No he ido por ese camino porque sé que terminaré enviándolo debido a la inercia de "funciona".
Soy autodidacta en lo que respecta a la interfaz y seguramente me estoy perdiendo algunos conocimientos fundamentales. ¿Alguna recomendación?
Lo descubrí, necesito usar componentes JSX en lugar de llamar a las funciones directamente. Sin embargo, me encantaría que alguien pudiera explicar exactamente por qué. También cambié mis componentes para que fueran funciones de flecha, pero estoy bastante seguro de que eso es innecesario.
ThreadBody ahora crea ThreadReplies como tal
const ThreadBody = (replies: any) => { let replyItems = []; for (let i = 0; i < replies.length; i++) { replyItems.push(<ThreadReply post={replies[i]} level={0} />); }Las respuestas al hilo ahora se ven así
const ThreadReply = ({ post, level }) => { const [isOpen, setIsOpen] = useState(true);Pasé casi dos días resolviendo esto, ¡así que no te sientas mal si te quedas atascado por unas horas!