You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中点击预订按钮后重新渲染slot-id组件的实现方案

解决方案

要实现点击预订按钮后立即更新对应时段的状态,核心是在本地维护已预订的时段ID集合,无需等待API响应即可更新视图,同时处理API请求的成功/失败情况以保证状态一致性。

具体修改步骤:

  1. 替换全局状态:移除全局的isOccupied,改用bookedSlots状态存储已预订的时段ID数组(初始为空),独立跟踪每个时段的本地状态。
  2. 优化预订函数:
    • 点击按钮时先将当前时段ID加入bookedSlots,触发即时视图更新
    • 调用预订API,若请求失败则把该时段ID从集合中移除,恢复原状态
  3. 调整渲染判断逻辑:时段显示“已占用”的条件为:API返回的slot.occupied为true,或该时段ID在本地bookedSlots集合中

修改后的完整代码

import React, { useEffect, useState } from 'react'
import axios from 'axios'
import '../App.css'
import { useNavigate } from 'react-router-dom'
import { gettingData } from '../api/getUserData'
import { handleLogout } from '../api/handleLogout'
import { getGroundNear } from '../api/getGroundNearby'
import { bookingSlot } from '../api/bookingSlot'

const Dashboard = () => {
    const navigate = useNavigate()
    const [userData, setUser] = useState(undefined)
    const [groundData, setGroundData] = useState([])
    const [currentTime, setCurrentTime] = useState(Date.now())
    // 存储本地已预订的slot ID集合
    const [bookedSlots, setBookedSlots] = useState([])

    axios.defaults.withCredentials = true;

    useEffect(() => {
        gettingData(setUser)
    }, [])

    useEffect(() => {
        console.log("usee 2")
        if (userData) {
            console.log(userData)
            getGroundNear(userData.pincode, 0, 50000, setGroundData)
        }
    }, [userData])

    const handleBooking = async (slotId, groundId, userId) => {
        // 先添加到本地集合,立即更新视图
        setBookedSlots(prev => [...prev, slotId])
        try {
            // 调用预订API(确保bookingSlot是异步函数,返回Promise)
            const result = await bookingSlot(slotId, groundId, userId)
            if (!result) {
                // API返回失败,回滚本地状态
                setBookedSlots(prev => prev.filter(id => id !== slotId))
            }
        } catch (error) {
            // 请求出错,回滚本地状态
            console.error('预订失败:', error)
            setBookedSlots(prev => prev.filter(id => id !== slotId))
        }
    }

    return (
        <div>
            <button onClick={() => { handleLogout(navigate) }}>Logout</button>

            <div>
                <h3>场地列表</h3>
                {groundData && groundData.length &&
                    groundData?.map((ground) => {
                        return (
                            <div id='cards' key={ground._id}>
                                <img src={ground.photo} alt='ground'></img>
                                <h4>{ground.ground}</h4>
                                <span>类型: </span><span>{ground.type}</span><br />
                                <span>{ground.discription}</span>

                                <div className='timings'>
                                    <div className='slots'>
                                        {ground?.slots?.map(slot => {
                                            // 判断时段是否已占用:API标记 或 本地已预订
                                            const isSlotOccupied = slot.occupied || bookedSlots.includes(slot._id)
                                            return (
                                                <div id='slot-id' key={slot._id}>
                                                    {!isSlotOccupied ? (
                                                        <button onClick={() => handleBooking(slot._id, slot.ground_id, userData._id)}>
                                                            {slot.time_start} - {slot.time_end}
                                                        </button>
                                                    ) : (
                                                        <button id='occupied-slot' style={{ border: '3px dotted red', cursor: 'not-allowed', backgroundColor: '#FF999C' }}>
                                                            {slot.time_start} - {slot.time_end}
                                                        </button>
                                                    )}
                                                </div>
                                            )
                                        })}
                                    </div>
                                </div>
                            </div>
                        )
                    })
                }
            </div>
        </div>
    )
}

export default Dashboard

额外提示:

  • 确保bookingSlot是异步函数(返回Promise),否则await逻辑会失效,需检查你的API封装代码
  • 给循环渲染的元素添加key属性(如ground._id和slot._id),符合React最佳实践,避免渲染警告
  • API失败时的回滚逻辑可避免本地状态与后端数据不一致的问题

内容的提问来源于stack exchange,提问作者Mohd Arslaan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 16:05:18