React票务预订应用座位选择故障求助:单按钮触发全选且计数异常
React票务预订应用选座功能问题修复
问题说明
自学React开发静态票务预订应用,使用Bootstrap做样式。选择票数后打开选座模态框,当前存在两个问题:
- 点击单个座位按钮时,所有按钮同步变色
- 票数计数仅能变化一次
现有代码
状态与处理函数
const [select,setSelect]=useState(0); const [seatCount,setSeatCount]=useState(select); const [toggleSeat,setToggleSeat]=useState(false); const ticketCountHandler=(e)=>{ setSelect(e.target.value); console.log(e.target.value); setSeatCount(e.target.value) } const ticketCount=Array.from({ length: 10 }, (_, index) => index + 1); const seatCountHandler=(e)=>{ e.preventDefault(); setToggleSeat(!toggleSeat); if(!toggleSeat){ setSeatCount(prev=>prev-1) }else{ setSeatCount(prev=>prev+1) } }
座位数下拉菜单
{/*count input start */} <div className="col-4"> <select id="count" value={select} onChange={ticketCountHandler} className='form-select'> <option selected disabled hidden>Select Ticket Count(max 10)</option> {ticketCount.map((value) => ( <option key={value} value={value}> {value} </option> ))} </select> </div> {/*count input end */}
座位选择模态框
<button type="button" class="btn form-control" data-bs-toggle="modal" data-bs-target="#seat-count"> Select Seats </button> <div class="modal fade" id="seat-count" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h1 class="modal-title fs-5" id="exampleModalLabel">Your Ticket Count {seatCount}</h1> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> </div> <div class="modal-body"> <div className="row"> <div className="col-1"></div> <div className="col-1 m-2"><button className='btn seat-btn disabled bg-danger'>100</button></div> <div className="col-1 m-2"><button className={`btn seat-btn ${toggleSeat?"bg-success":""}`} value={101} onClick={seatCountHandler}>101</button></div> <div className="col-1 m-2"><button className={`btn seat-btn ${toggleSeat?"bg-success":""}`} value={102} onClick={seatCountHandler}>102</button></div> <div className="col-1"></div> <div className="col-1 m-2"><button className={`btn seat-btn ${toggleSeat?"bg-success":""}`} value={103} onClick={seatCountHandler}>103</button></div> <div className="col-1 m-2"><button className={`btn seat-btn ${toggleSeat?"bg-success":""}`} value={104} onClick={seatCountHandler}>104</button></div> <div className="col-1 m-2"><button className={`btn seat-btn ${toggleSeat?"bg-success":""}`} value={105} onClick={seatCountHandler}>105</button></div> <div className="col-1"></div> <div className="col-1"></div> </div> </div> </div> </div> </div>
问题原因与修复方案
问题1:所有座位同步变色
当前用单个布尔值toggleSeat控制所有座位的选中状态,点击任意座位都会触发全局状态更新,导致所有按钮样式同步变化。需改为记录已选中的座位ID集合,而非单个布尔值。
问题2:票数计数仅能变化一次
seatCountHandler中依赖toggleSeat的当前值增减计数,但setToggleSeat是异步更新,导致逻辑判断出错。同时,计数逻辑应基于单个座位的选中/取消状态,而非全局开关。
修复后的代码
状态调整
// 用数组存储已选中的座位ID const [selectedSeats, setSelectedSeats] = useState([]); const [select, setSelect] = useState(0); // 剩余可选座位数 = 总票数 - 已选座位数 const remainingSeats = select - selectedSeats.length;
座位点击处理函数修改
const seatCountHandler = (e) => { e.preventDefault(); const seatId = e.target.value; // 判断当前座位是否已选中 if (selectedSeats.includes(seatId)) { // 取消选中:移除对应座位ID setSelectedSeats(prev => prev.filter(id => id !== seatId)); } else { // 选中:仅当还有剩余座位时添加 if (remainingSeats > 0) { setSelectedSeats(prev => [...prev, seatId]); } } }
模态框座位按钮样式修改
每个座位按钮根据自身ID是否在selectedSeats数组中判断样式,同时添加禁用逻辑:
<div className="col-1 m-2"> <button className={`btn seat-btn ${selectedSeats.includes("101") ? "bg-success" : ""}`} value="101" onClick={seatCountHandler} disabled={remainingSeats === 0 && !selectedSeats.includes("101")} > 101 </button> </div> <div className="col-1 m-2"> <button className={`btn seat-btn ${selectedSeats.includes("102") ? "bg-success" : ""}`} value="102" onClick={seatCountHandler} disabled={remainingSeats === 0 && !selectedSeats.includes("102")} > 102 </button> </div> // 其他座位按钮按相同逻辑修改
模态框标题更新
<h1 class="modal-title fs-5" id="exampleModalLabel"> 已选座位:{selectedSeats.length}/{select} </h1>
额外优化
- 移除冗余状态
seatCount,直接通过select - selectedSeats.length计算剩余座位数,减少状态维护成本 - 添加按钮禁用逻辑,避免用户选择超过预订票数的座位
内容的提问来源于stack exchange,提问作者Y Nawodya
相关产品推荐
相关产品推荐

