Sharing State - Row & Seat Components
Read about how to share state in the row component this lesson.
We'll cover the following...
The rows in the venue body are the same as before, except we are passing the number of tickets to buy as a new prop in the object.
The Row
component has gotten a lot more functionality, some of which has been taken from the Seat
component. In this version of the code, the status of a seat depends on the status of the seats next to it—if the tickets to buy number is two, then a set with an already sold seat next to it is not available. Because an individual seat can no longer contain all the data needed to ascertain it’s status, the status for the entire row now needs to be stored in the Row
component.
Here’s the Row
code:
import * as React from "react"import Seat from "../components/seat"interface RowProps {rowNumber: numberseatsInRow: numberticketsToBuy: number}const Row = (props: RowProps) => {const [seatStatuses, setSeatStatuses] = React.useState(Array.from(Array(props.seatsInRow).keys()).map(() => "open"))function isSeatValid(seatNumber): boolean {if (seatNumber + props.ticketsToBuy > props.seatsInRow) {return false}for (let i = 1; i < props.ticketsToBuy; i++) {if (seatStatuses[seatNumber + i] === "held") {return false}}return true}function validSeatStatus(seatNumber): string {if (seatStatuses[seatNumber] === "held") {return "held"} else {return isSeatValid(seatNumber) ? "open" : "invalid"}}function newState(oldStatus: string): string {if (oldStatus === "open") {return "held"} else if (oldStatus === "held") {return "open"} else {return "invalid"}}function onSeatChange(seatNumber: number): void {if (validSeatStatus(seatNumber) === "invalid") {return}setSeatStatuses(seatStatuses.map((status, index) => {if (index >= seatNumber && index < seatNumber + props.ticketsToBuy) {return newState(seatStatuses[seatNumber])} else {return status}}))}const seatItems = Array.from(Array(props.seatsInRow).keys()).map(seatNumber => {return (<Seatkey={seatNumber}seatNumber={seatNumber}status={validSeatStatus(seatNumber)}clickHandler={onSeatChange}/>)})return <tr>{seatItems}</tr>}export default Row
This component does two important things: First, it keeps track of the seat statuses in an array. Second, it defines a click handler to be executed when a seat is clicked. To make that work, the Row
component passes that handler function as a prop to the Seat
component, namely clickHandler
.
The first thing that we need to do is we call the useState
hook again on line 11, this time to create an array of seat statuses. The initial value, which is the argument to the useState
call, is an array of open
values, one for each seat in the row.
Using an array or an object as the value of the state in a useState
call, rather than an individual value, is a little bit different than you might expect. It is important to keep in mind that the argument to the useState
method is only applied to the state value the first time the component is drawn. When the component re-renders, that value is ignored. An implication of that is that, as a general rule, you don’t want the argument to the useState
method to be dynamic. In our case, it’s just an array of open
values since we don’t expect the number of seats in the row to change.
Later, in ...