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

React中点击Hero组件按钮修改HotelCards组件guests值的实现方案

React跨组件更新状态实现方案

你当前的Hero和HotelCards为同级兄弟组件,无法直接互相调用内部的state更新方法,以下是两种可直接落地的实现方案。

注意:你现有代码中直接导出普通全局变量跨文件修改的写法不可行,普通变量修改不会触发React重渲染,会出现值变更但页面不更新的问题。


方案1:状态提升(React官方推荐)

核心逻辑是将两个组件共享的guests状态,提升到二者的共同父组件维护,通过props向下传递状态和更新方法:

  • 在父组件中定义guests状态和对应的更新函数
  • 将更新函数作为prop传给Hero组件,Search按钮点击时调用该方法更新状态
  • 将guests状态值作为prop传给HotelCards组件,替换组件内部原有的本地guests状态

代码示例

  1. 共同父组件(如页面级组件HotelPage.jsx)
import React, { useState } from 'react'
import Hero from './Hero'
import HotelCards from './Hotelcards'

export default function HotelPage() {
  // 共享状态提升到父组件维护
  const [guests, setGuests] = useState('')

  const handleSearch = () => {
    // 替换为你需要给guests设置的实际值
    setGuests(2)
  }

  return (
    <div>
      {/* 传递更新方法给Hero */}
      <Hero onSearch={handleSearch} />
      {/* 传递状态值给HotelCards */}
      <HotelCards 
        guests={guests}
        idroom={/* 原有props正常传递 */}
        title={/* 原有props正常传递 */}
        status={/* 原有props正常传递 */}
        price={/* 原有props正常传递 */}
        img={/* 原有props正常传递 */}
      />
    </div>
  )
}
  1. Hero.jsx 修改部分
// 接收父组件传递的onSearch方法
export default function Hero({ onSearch }) {
    const [availdata, setavailData] = useState([]);
    const [isLoading, setIsLoading] = useState(false);

    // 原有业务逻辑保持不变

    return (
      <>
        {/* 原有其他UI结构保持不变 */}
        <div className="search">
          <button onClick={onSearch}>Search</button>
        </div>
      </>
    )
}
  1. Hotelcards.jsx 修改部分
// 接收父组件传递的guests参数
const HotelCards = ({ idroom , title, status = true, price, img, guests  }) => {
    // 删除原有本地guests状态定义:const [guests, setGuest] = useState('')

    const [qty, setTitle] = useState('')
    var total_price = 0;
    if(prices.length!==0){
        for (var i=0;i<prices.length-1;i++){
            total_price+=parseFloat(prices[i]);
        }
    }

    // 组件内其他用到guests的逻辑无需修改,直接使用props传入的值即可
};

方案2:轻量事件总线(适合组件层级跨度大的场景)

如果两个组件嵌套层级很深,层层传递props维护成本太高,可以实现一个简单的发布订阅模块做通信,无需引入第三方依赖:

  1. 新建eventBus.js文件实现基础事件能力
// eventBus.js
const eventStore = {}
export default {
  // 订阅事件
  on(eventName, callback) {
    if (!eventStore[eventName]) eventStore[eventName] = []
    eventStore[eventName].push(callback)
  },
  // 触发事件
  emit(eventName, payload) {
    if (eventStore[eventName]) {
      eventStore[eventName].forEach(cb => cb(payload))
    }
  },
  // 取消订阅
  off(eventName, callback) {
    if (eventStore[eventName]) {
      eventStore[eventName] = eventStore[eventName].filter(cb => cb !== callback)
    }
  }
}
  1. Hero.jsx 中触发事件
import eventBus from './eventBus'

export default function Hero() {
    const [availdata, setavailData] = useState([]);
    const [isLoading, setIsLoading] = useState(false);

    const handleSearchClick = () => {
      // 触发guests更新事件,传入要设置的目标值
      eventBus.emit('updateGuests', 2)
    }

    return (
      <>
        {/* 原有UI结构 */}
        <div className="search">
          <button onClick={handleSearchClick}>Search</button>
        </div>
      </>
    )
}
  1. Hotelcards.jsx 中监听事件更新本地状态
import eventBus from './eventBus'
import { useEffect } from 'react'

const HotelCards = ({ idroom , title, status = true, price, img  }) => {
    const [guests, setGuest] = useState('')

    // 组件挂载时订阅事件,卸载时取消订阅避免内存泄漏
    useEffect(() => {
      const updateGuestValue = (targetVal) => {
        setGuest(targetVal)
      }
      eventBus.on('updateGuests', updateGuestValue)
      return () => {
        eventBus.off('updateGuests', updateGuestValue)
      }
    }, [])

    const [qty, setTitle] = useState('')
    var total_price = 0;
    if(prices.length!==0){
        for (var i=0;i<prices.length-1;i++){
            total_price+=parseFloat(prices[i]);
        }
    }
};

内容的提问来源于stack exchange,提问作者Charfeddine Mohamed Ali

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.10 16:15:47