skip to Main Content

So, I’m trying to create a simple program in react. The state is an array of objects. It prints these objects into a table. Standard table construction (, , ) etc. works fine for the initial render, but when I try to re-render I get bizarre errors I’m trying to adapt to. So, this is my code so far.

import React from "react";
import ReactDOM from "react-dom";
import { useState } from "react";
import "./style.css";

function Trains() {
  const [trainsList, setTrainsList] = useState([
    { name: "Thomas", destination: "Boston" },
    { name: "Duncan", destination: "New York" },
  ]);

  return (
    <div>
      <table>
        <thead>name</thead>
        <thead>destination</thead>

        {trainsList.map((train) => (
          <tbody key={train.name}>
            <td>{train.name}</td>
            <td>{train.destination}</td>
          </tbody>
        ))}
      </table>
      <br />
      Train Name: <input type="text" id="trainName" />
      <br />
      Destination: <input type="text" id="trainDest" />
      <br />
      <button
        onClick={() =>
          setTrainsList((prev) =>
            prev.push({ name: "Dennis", destination: "Denville" })
          )
        }
      >
        Submit
      </button>
    </div>
  );
}

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<Trains />);

But even changing the table lingo like that still isn’t enough. I get these bizarre errors:

bundle.js:7294 Warning: validateDOMNesting(...): Text nodes cannot appear as a child of <thead>.
    at thead
    at table
    at div
    at Trains (http://localhost:3000/static/js/bundle.js:32:86)

And

bundle.js:7294 Warning: validateDOMNesting(...): <td> cannot appear as a child of <tbody>.
    at td
    at tbody
    at table
    at div
    at Trains (http://localhost:3000/static/js/bundle.js:32:86)

How on Earth can I create a table or use "thead" to any effect if I can’t even put any text in the headings or put tds in my table rows? How the heck do I make tables in react?

2

Answers


  1. Table Rows

    You’ve probably intended to make your table look something like that:

    <table>
      <thead>
        <tr>
          <th>name</th>
          <th>destination</th>
        </tr>
      </thead>
    
      <tbody>
        {trainsList.map((train) => (
          <tr key={index}>
            <td>{train.name}</td>
            <td>{train.destination}</td>
          </tr>
        ))}
      </tbody>
    </table>
    
    

    Note the <tr> elements to create a table rows both in the header and in the body.

    Key in a map

    Also, note the key attribute in the <tr> element. It is not a good practice to use an index of an array as a key, although it is much better that using a name that can be repeated.

    Fix setState

    Finally, the function to update state after clicking a button can be rewritten to that:

    <button
      onClick={() =>
        setTrainsList((prev) => {
          return [
            ...prev,
            { name: "Dennis", destination: "Denville" },
          ];
        })
      }
    >
      Submit
    </button>
    
    Login or Signup to reply.
  2. The error is in the setTrainsList method defined in the Submit button. The push method returns the new length of the array, but does not change the original array. Instead, you must use the concat method or the spread syntax to add a new element to an array in React:

    <button onClick={() =>
        setTrainsList((prev) => [...prev, { name: "Dennis", destination: "your butt" }])
      }
    >
      Submit
    </button>
    

    This should resolve the error and add a new element to the train list when you click the button.

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