Search code examples
javascriptreactjsreact-dom

Text nodes cannot appear as a child of <table> [ReactJS]; Warning: Each child in a list should have a unique "key" prop


I can see the table on the screen and all the information from the db.json is imported. When I open console it shows me these errors: Text nodes cannot appear as a child of <table> [ReactJS]; Warning: Each child in a list should have a unique "key" prop. I tried changing div to fragment but it isn't working. How can I solve this?

return (
  <div className='container'>
    <table className="table">
      <thead>
        <tr className='bg-dark text-white'>
          <th scope="col">#</th>
          <th scope="col">Product Name</th>
          <th scope="col">Product Number</th>
          <th scope="col">Color</th>
          <th scope="col">List Price</th>
          <th scope="col">Modified Date</th>
          <th scope="col">Action</th>  
        </tr>
      </thead>
      <tbody>
        {products.map((product, index) => (
          <tr>
            <th scope='row'> {index + 1}</th>
            <td>{product.name}</td>   
            <td>{product.number}</td> 
            <td>{product.color}</td> 
            <td>{product.price}</td> 
            <td>{product.date}</td> 
            <td>
              <Link className='btn btn-primary m-2'><i className="fa fa-eye" aria-hidden="true"></i></Link>
              <Link className='btn btn-otline-primary m-2'>Edit</Link>
              <Link className='btn btn-danger m-2'>Delete</Link>
            </td> 
          </tr>
        ))};
      </tbody>
    </table>
    <Link className='btn btn-outline-dark w-25' to='/product/add'>
      Add Product
    </Link>
  </div>
);
}

Solution

  • Text nodes cannot appear as a child of <table>

    There is a trailing semi-colon at the end of the tbody element, out there on it's own. Remove this.

    <table className="table">
      <thead>
        <tr className='bg-dark text-white'>
          <th scope="col">#</th>
          <th scope="col">Product Name</th>
          <th scope="col">Product Number</th>
          <th scope="col">Color</th>
          <th scope="col">List Price</th>
          <th scope="col">Modified Date</th>
          <th scope="col">Action</th>  
        </tr>
      </thead>
      <tbody>
        {products.map((product, index) => (
          <tr>
            <th scope='row'> {index + 1}</th>
            <td>{product.name}</td>   
            <td>{product.number}</td> 
            <td>{product.color}</td> 
            <td>{product.price}</td> 
            <td>{product.date}</td> 
            <td>
              <Link className='btn btn-primary m-2'><i className="fa fa-eye" aria-hidden="true"></i></Link>
              <Link className='btn btn-otline-primary m-2'>Edit</Link>
              <Link className='btn btn-danger m-2'>Delete</Link>
            </td> 
          </tr>
        ))}; // <-- remove trailing text node
      </tbody>
    </table>
    

    Warning: Each child in a list should have a unique "key" prop.

    When mapping an array to JSX the outer-most mapped element needs a React key. The React key should be unique among the siblings. id and other GUIDs properties make for great React keys, but the array index is ok as a fallback so long as the array isn't being mutated.

    Example:

    <tbody>
      {products.map((product, index) => (
        <tr key={product.id}> // <-- React key on outer element
          <th scope='row'>{index + 1}</th>
          <td>{product.name}</td>   
          <td>{product.number}</td> 
          <td>{product.color}</td> 
          <td>{product.price}</td> 
          <td>{product.date}</td> 
          <td>
            <Link className='btn btn-primary m-2'>
              <i className="fa fa-eye" aria-hidden="true" />
            </Link>
            <Link className='btn btn-otline-primary m-2'>Edit</Link>
            <Link className='btn btn-danger m-2'>Delete</Link>
          </td> 
        </tr>
      ))}
    </tbody>
    

    See Lists and Keys for more details/information on React key usage.