Search code examples
javascriptreactjsrendering

React- problems rendering table


I'm creating a react SPA, my problem is that when I go to the page where my table is only the TableRow information that is rendered, I've tried using conditional rendering but I still have the same problem.

this is the page with the table component(sumariosDenseTable):

import React, { useState, useEffect } from 'react';

import { Container } from './styles';

import SumariosDenseTable from '../../components/SumariosDenseTable';

export default function Sumarios() {
  return (
    <Container>
      <div className="title">Listar Sumários</div>

      <SumariosDenseTable />

    </Container>
  );
}

when I'm redirected to this page only TableHead information is rendered.

this is the table component code:

function createData(conteudo, disciplina, curso, dataAula) {
  return { conteudo, disciplina, curso, dataAula };
}

const rows = [];

export default function SumariosDenseTable() {
  const { sumarios } = useListarSumarios();
  const { cursoSigla } = useListarAulas();

  React.useEffect(() => {
    if (rows.length !== sumarios.length) {
      sumarios.map((sum) =>
        rows.push(
          createData(
            sum.sumario.conteudo,
            sum.disciplina.codigo,
            cursoSigla(sum.cursos),
            sum.data
          )
        )
      );
    }
  }, [sumarios, rows]);

  return (
    <TableContainer component={Paper}>
      <Table sx={{ minWidth: 650 }} size="small" aria-label="a dense table">
        <TableHead>
          <TableRow>
            <TableCell>Conteudo</TableCell>
            <TableCell align="right">Disciplina</TableCell>
            <TableCell align="right">Cursos</TableCell>
            <TableCell align="right">Data</TableCell>
          </TableRow>
        </TableHead>

        <TableBody>
          {rows.map((row) => (
            <TableRow
              key={row.conteudo}
              sx={{ '&:last-child td, &:last-child th': { border: 0 } }}
            >
              <TableCell component="th" scope="row">
                {row.conteudo}
              </TableCell>
              <TableCell align="right">{row.disciplina}</TableCell>

              <TableCell align="right">{row.curso}</TableCell>

              <TableCell align="right">{row.dataAula}</TableCell>
            </TableRow>
          ))}
        </TableBody>
      </Table>
    </TableContainer>
  );
}

the problem is that the table component is rendered before the rows array is completely filled how do I get the table to be rendered only when the row array is completely filled ???


Solution

  • You need to use useState (state hook) for the rows variable. This way, when the useEffect is done populating the rows variable, the component will be re-rendered.

    You can learn more about the state hook here.

    The code should look like this (explanation added as comments):

    // Add useState import at the top
    import { useState } from "react";
    
    // All other imports and the rest of the top half of your code are still here
    
    export default function SumariosDenseTable() {
        const { sumarios } = useListarSumarios();
        const { cursoSigla } = useListarAulas();
    
        // Use useState for the rows and set it's initial value to empty ([])
        const { rows, setRows } = useState([]);
    
        React.useEffect(() => {
            if (rows.length !== sumarios.length) {
                const tempRows = [];
                sumarios.map((sum) =>
                    tempRows.push(
                        createData(
                            sum.sumario.conteudo,
                            sum.disciplina.codigo,
                            cursoSigla(sum.cursos),
                            sum.data
                        )
                    )
                );
    
                // update the rows variable via the hook
                setRows(tempRows);
            }
        }, [sumarios, rows]);
    
        if (rows.length > 0) {
            return (
                <TableContainer component={Paper}>
                   //The rest of the table code here
                </TableContainer>
            );
        } else {
            // If no rows, don't render anything at all
            return null;
        }
    }