skip to Main Content

I’m encountering an issue in my React application where I’m rendering a table with dynamic rows using components. However, the rows are being treated as separate elements instead of components within the table body.

Despite generating the rows dynamically using components, they’re not aligning properly with the table headers. I’ve tried various approaches, including encapsulating each row within its own element, but the issue persists.

  1. TableHead Component:
function TableHead({ rowCount }) {
  return (
    <div className='table-container'>
      <table>
        <thead>
          <tr>
            <th>S. No</th>
            <th>Subject</th>
            <th>Grade</th>
          </tr>
        </thead>
        <tbody>
          <tr><InitialRender count={rowCount} /></tr>
        </tbody>
      </table>
    </div>
  );
}

  1. InitialRender Component:
function InitialRender({ count }) {
  const initialRows = [];
  for (let i = 0; i < count; i++) {
    initialRows.push(
      <TableRow key={i + 1} count={i + 1} />
    );
  }

  return initialRows;
}
  1. TableRow Component
function TableRow({ count }) {
  return (
    <tr>
      <td>{count}</td>
      <td><input type="text" placeholder='Enter subject' /></td>
      <td>
        <select name="" id="dropdown">
          <option value="">Grades</option>
          <option value="O">O</option>
          <option value="A+">A+</option>
          <option value="A">A</option>
          <option value="B+">B+</option>
          <option value="B">B</option>
          <option value="AB">AB</option>
        </select>
      </td>
    </tr>
  );
}

  1. App Component:
function App() {
  const [rowCount, setRowCount] = useState(6);

  const handleAddRow = () => {
    setRowCount(prevCount => prevCount + 1);
  };

  return (
    <div className='form-container'>
      <form action=''>
        <TableHead rowCount={rowCount} />
        <InitialRender count={rowCount} />
        <div className='buttons'>
          <AddRow onAddRow={handleAddRow} />
          <Submit />
        </div>
      </form>
    </div>
  );
}

2

Answers


  1. The TableHead component already has the InitialRender as a child and you are calling it again from App. You need to remove <InitialRender count={rowCount} /> from App component. The TableHead will call it.

    (I have removed <form> from the App here in the snippet, you can add it back.)

    const { useState } = React;
    
    function App() {
      const [rowCount, setRowCount] = useState(6);
    
      const handleAddRow = (event) => {
      event.preventDefault;
        setRowCount(prevCount => prevCount + 1);
      };
    
      return (
        <div className='form-container'>
            <TableHead rowCount={rowCount} />
            <div>
            <button onClick={handleAddRow}> Add row  </button>
            </div>
         
        </div>
      );
    }
    
    function TableRow({ count }) {
      return (
        <tr>
          <td>{count}</td>
          <td><input type="text" placeholder='Enter subject' /></td>
          <td>
            <select name="" id="dropdown">
              <option value="">Grades</option>
              <option value="O">O</option>
              <option value="A+">A+</option>
              <option value="A">A</option>
              <option value="B+">B+</option>
              <option value="B">B</option>
              <option value="AB">AB</option>
            </select>
          </td>
        </tr>
      );
    }
    
    function InitialRender({ count }) {
      const initialRows = [];
      for (let i = 0; i < count; i++) {
        initialRows.push(
          <TableRow key={i + 1} count={i + 1} />
        );
      }
    
      return initialRows;
    }
    
    function TableHead({ rowCount }) {
      return (
        <div className='table-container'>
          <table>
            <thead>
              <tr>
                <th>S. No</th>
                <th>Subject</th>
                <th>Grade</th>
              </tr>
            </thead>
            <tbody>
              <InitialRender count={rowCount} />
            </tbody>
          </table>
        </div>
      );
    }
    
    ReactDOM.createRoot(document.getElementById("app")).render(<App />);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js" integrity="sha512-8Q6Y9XnTbOE+JNvjBQwJ2H8S+UV4uA6hiRykhdtIyDYZ2TprdNmWOUaKdGzOhyr4dCyk287OejbPvwl7lrfqrQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js" integrity="sha512-MOCpqoRoisCTwJ8vQQiciZv0qcpROCidek3GTFS6KTk2+y7munJIlKCVkFCYY+p3ErYFXCjmFjnfTTRSC1OHWQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    
    
    <div id="app"></div>
    Login or Signup to reply.
  2. Some nitpicking:

    First since you are using react you should divide the program in actual framgents.

    Your TableRow is fine but your tableHead should either be renamed to table since you are making a table and not the header.

    Your problem:

    Both in TableHead and the App you are calling for the InitialRender, since you are already calling it on your TableHeader remove it from the app. The InitialRender you had in the app was not inside the table so that created your problem

     return (
    <div className='form-container'>
      <form action=''>
        <TableHead rowCount={rowCount} />
        <div className='buttons'>
          <AddRow onAddRow={handleAddRow} />
          <Submit />
        </div>
      </form>
    </div>
    

    If you do that it looks at it should table

    More nitpicking:

    You could also just remove completely your InitialRender using something like this on your TableHeader

    <table>
            <tr>
                <th>S. No</th>
                <th>Subject</th>
                <th>Grade</th>
            </tr>
            <tbody>
                {Array.from({ length: options }, (_, index) => (
                    <TableRow key={index} count={index} />
                ))}
            </tbody>
    

    Using the Array.from() making you a loop reducing you a function but yours still good.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search