All the bills that you add are shown in the page through the BillsTable component.

We want it to be a table, and display the contents of the bills array that’s passed down from App. So here’s what we can do:

import React from 'react'

export default props => {
  return (
    <table className="table">
      <thead className="bg-blue text-white">
        <tr>
          <th scope="col">Date</th>
          <th scope="col">Amount</th>
          <th scope="col">Category</th>
          <th scope="col" />
        </tr>
      </thead>
      <tbody>
        {props.bills.map((value, index) => {
          return (
            <tr className="p4" key={index}>
              <td>{value.date}</td>
              <td>${value.amount}</td>
              <td>{value.category}</td>
            </tr>
          )
        })}
      </tbody>
    </table>
  )
}

It’s a lot like we did to iterate on categories in the NavBar component: we use map() to repeat the tr element for every bill.

Let’s set the initial state of shouldShowAddBill to false, so we can see the bills list. First add some example bills, so you can see them in the list:

const [shouldShowAddBill, setShouldShowAddBill] = useState(false)

Next in the App JSX we pass bills as a prop to BillsTable:

<BillsTable bills={bills} />

Now the date is displayed in this format: 2019-01-30T15:08:26.118Z. This is machine-readable, not human readable. We can use the popular moment library, via the react-moment package.

Install it by adding react-moment as a CodeSandbox dependency, or using npm:

npm install moment react-moment

Once you do so, we can import it

import Moment from 'react-moment'

and you can format the date by just wrapping it in the Moment component, using the format prop:

<Moment format="MMM D YYYY">{value.date}</Moment>

The MMM D YYYY string is the format of the date, and it means print the month name followed by the day number and the year.

This is what we’ll do in BillsTable:

<tbody>
  {props.bills.map((value, index) => {
    return (
      <tr className="p4" key={index}>
        <td><Moment format="MMM D YYYY">{value.date}</Moment></td>
        <td>${value.amount}</td>
        <td>{value.category}</td>
      </tr>
    )
  })}
</tbody>

Now let’s add something to the list: we want to add a small button that shows the AddBill component so we can add bills. I chose to make it part of the table, and span across an entire table row. Add it inside the tbody tag, before you iterate over the bills:

<tr>
  <td colSpan="4">
    <button className="underline" onClick={triggerShowAddBill}>Add new</button>
  </td>
</tr>

triggerShowAddBill is a function we’re going to put inside the BillsTable component:

const triggerShowAddBill = () => {
  props.showAddBill()
}

this method calls the parent (App component) showAddBill method, which sets the shouldShowAddBill state property to true by calling setShouldShowAddBill():

const showAddBill = () => {
  setShouldShowAddBill(true)
}

We then pass it as a prop to BillsTable:

<BillsTable bills={bills} showAddBill={showAddBill} />

When this happens, the app shows the AddBill component, because that’s how we organized our App component JSX.

Notice that by passing bills in this way, the BillsTable component will automatically refresh its displayed output when we add a new bill.

Now the app should show the bills at startup, and if you click “Add bill”, you should see the AddBill component. You can add a new bill, and you should see the list again, with the new bill added.

We add a little bit of styling to BillsTable to make it pretty, by adding Tailwind classes, and we’re good to go:

import React from 'react'
import Moment from 'react-moment'

export default props => {
  const triggerShowAddBill = () => {
    props.showAddBill()
  }

  return (
    <table className="table">
      <thead className="bg-blue text-white">
        <tr>
          <th scope="col">Date</th>
          <th scope="col">Amount</th>
          <th scope="col">Category</th>
          <th scope="col" />
        </tr>
      </thead>
      <tbody>
        <tr className="p-4 bg-blue-lighter text-center">
          <td colSpan="4">
            <button className="underline" onClick={triggerShowAddBill}>
              Add new
            </button>
          </td>
        </tr>
        {props.bills.map((value, index) => {
          return (
            <tr className="p4" key={index}>
              <td>
                <Moment format="MMM D YYYY">{value.date}</Moment>
              </td>
              <td>${value.amount}</td>
              <td>{value.category}</td>
            </tr>
          )
        })}
      </tbody>
    </table>
  )
}

See the app in the current state on CodeSandbox.


Go to the next lesson