Adding Our First Component

Learn how to add a component using React in this lesson.

Using React for concert seats

Let’s take a moment to discuss what we’ll be doing with React. The concert display page was part of our original Rails app, but we haven’t looked at it closely yet. It currently has a grid of seats that we’d like to use to allow people to select which seat they want to purchase at the particular concert being displayed.

Right now, it’s a grid of squares in an HTML table:

Press + to interact
<table class="table">
<tbody>
<% @concert.venue.rows.times do |row| %>
<tr>
<% @concert.venue.seats_per_row.times do |seat| %>
<% ticket = @concert.find_ticket_at(
row: row + 1,
number: seat + 1
) %>
<td>
<%= link_to(ticket_path(ticket.id),
method: :patch) do %>
<div class="<%= ticket.color_for(current_user) %>
p-4 m-2 border-black border-4 button
hover:bg-blue-300 text-lg">
<%= seat + 1 %>
</div>
<% end %>
</td>
<% end %>
</tr>
<% end %>
</tbody>
</table>

The page also has a pull-down menu to select the number of tickets, but we’ll get to that later.

The first thing we are going to do is convert this code so React can control that part of the page. Eventually we are going to add interactivity to allow a user to select seats, show a running total, and show the current status of seat purchases. First, let’s simply draw the table in React.

This feature has great potential for React because it’s interactive but doesn’t use traditional browser form elements that might already have built-in browser functionality.

React encourages us to split our page into small components. To draw this section of the page, we’re going to have three components: one for each individual seat, one for each row that contains a row’s worth of seats, and one for the venue itself, which combines all the rows.

Here’s a screenshot of the page with the boundaries of our eventual React components, “Venue”, “Row”, and “Seat”, marked:

The application would look something like this:

module.exports = {
  purge: [],
  darkMode: false, // or 'media' or 'class'
  theme: {
    extend: {},
  },
  variants: {
    extend: {},
  },
  plugins: [
    require('@tailwindcss/forms'),
    require('@tailwindcss/typography'),
    require('@tailwindcss/aspect-ratio'),
  ],
}

The Seat component

...