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

如何在React中通过复选框对API返回的酒店数据按星级筛选展示

实现方案

核心逻辑调整说明

  • 不要手动调用document.createElement操作DOM,React基于状态驱动视图,只要更新对应状态就会自动渲染对应内容,手动操作的DOM会被React虚拟DOM渲染覆盖,所以不会生效
  • 不要在复选框的onChange事件中重复调用接口拉取数据,全量数据拉取一次后存在本地做筛选即可,减少不必要的接口请求
  • 新增两个状态分别存储全量原始数据和选中的筛选项,避免筛选后丢失原始数据

完整修改后代码

import { useState, useEffect } from 'react'
import Header from './Header' // 请根据自己的项目路径调整Header组件的引入

export default function App() {
  // 存储全量原始酒店数据,避免筛选后丢失源数据
  const [allHotelRooms, setAllHotelRooms] = useState([]);
  // 存储用户选中的星级筛选项
  const [selectedStarRatings, setSelectedStarRatings] = useState([]);
  // 存储筛选后的酒店列表
  const [filteredHotels, setFilteredHotels] = useState([]);

  const fetchHotels = async () => {
    const res = await fetch('https://obmng.dbm.guestline.net/api/hotels?collection-id=OBMNG')
    const hotels = await res.json()
    
    const hotelRooms = []
    for(const hotel of hotels) {
      const res = await fetch(`https://obmng.dbm.guestline.net/api/roomRates/OBMNG/${hotel.id}`)
      const info = await res.json()
      hotelRooms.push({ hotel, rooms: info.rooms })
    }
    // 全量数据和初始筛选结果都赋值为拉取到的全部数据
    setAllHotelRooms(hotelRooms)
    setFilteredHotels(hotelRooms)
  }

  useEffect(() => {
    fetchHotels()
  }, [])

  // 星级复选框切换处理函数
  const handleStarChange = (star) => {
    let newSelected = []
    if (selectedStarRatings.includes(star)) {
      // 已选中对应星级则移除筛选项
      newSelected = selectedStarRatings.filter(item => item !== star)
    } else {
      // 未选中对应星级则添加筛选项
      newSelected = [...selectedStarRatings, star]
    }
    setSelectedStarRatings(newSelected)

    // 执行筛选逻辑
    if (newSelected.length === 0) {
      // 无选中星级时展示全部酒店
      setFilteredHotels(allHotelRooms)
    } else {
      // 筛选出星级匹配的酒店
      const result = allHotelRooms.filter(h => newSelected.includes(h.hotel.starRating))
      setFilteredHotels(result)
    }
  }

  return (
    <div className="App">
      <Header/>
      {/* 星级筛选区域 */}
      <div style={{padding: '10px', borderBottom: '1px solid #eee'}}>
        <h3>按星级筛选:</h3>
        {[1,2,3,4,5].map(star => (
          <label key={star} style={{marginRight: '15px'}}>
            <input
              type="checkbox"
              checked={selectedStarRatings.includes(star)}
              onChange={() => handleStarChange(star)}
            />
            {star}星
          </label>
        ))}
      </div>

      {/* 渲染筛选后的酒店列表 */}
      {
        filteredHotels.map(h => (
          <div key={h.hotel.id} style={{padding: '15px', borderBottom: '1px solid #eee'}}>
            <h2> 名称: {h.hotel.name}</h2>
            <p> 描述: {h.hotel.description}</p>
            <p> 星级: {h.hotel.starRating}</p>
            <p> 邮编: {h.hotel.postcode}</p>
            <p> 城市: {h.hotel.town}</p>
            <img src={h.hotel.images?.[0]?.url || ''} alt={h.hotel.name} />
            <p style={{ fontWeight: 'bold' }}>房型:</p>
            {
              h.rooms.map(room => (
                <div key={room.id} style={{paddingLeft: '20px', marginTop: '10px'}}>
                  <h5>入住人数限制</h5>
                  <div> 成人最多: {room.occupancy.maxAdults}</div>
                  <div> 儿童最多: {room.occupancy.maxChildren}</div>
                  <div> 总人数最多: {room.occupancy.maxOverall}</div>
                  <div> 房型: {room.name}</div>
                  <img src={room.images?.[0]?.url || ''} alt={room.name} />
                </div>
              ))
            }
          </div>
        ))
      }
    </div>
  )
}

额外优化提示

  • 原代码中直接写img src={h.hotel.images}是错误的,接口返回的images是数组,需要取数组内的url字段才能正常展示图片
  • 列表遍历渲染必须添加key属性,避免React渲染报错

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 19:54:05