React中如何在一个函数组件内触发另一个函数组件重新渲染
React跨组件触发重渲染实现方案
以下是3种可行的实现方式,可根据项目场景选择:
方案1:状态提升到公共父组件(最推荐)
A、B的公共父组件是App,将触发重渲染的状态放到App中维护,符合React单向数据流设计,维护成本最低。
代码示例
// App.js import { useState } from 'react' import A from './A' import B from './B' export default function App() { // 用于触发B组件更新的状态 const [bRefreshFlag, setBRefreshFlag] = useState(0) return ( <> <A setBRefreshFlag={setBRefreshFlag} /> <B refreshFlag={bRefreshFlag} /> </> ) }
// A.js export default function A({ setBRefreshFlag }) { const foo = () => { // 执行foo时更新标记,触发B重渲染 setBRefreshFlag(prev => prev + 1) // 其余foo业务逻辑 } return <button onClick={foo}>触发foo</button> }
// B.js // 只要props的refreshFlag发生变化,B组件就会自动触发重渲染 export default function B({ refreshFlag }) { return <div>B组件当前渲染标记:{refreshFlag}</div> }
方案2:发布订阅模式(EventBus)
适合组件层级深、透传props成本高的场景,无需修改父组件逻辑。
代码示例
// eventBus.js 单独创建公共事件调度文件 const EventBus = { eventMap: {}, on(eventName, callback) { if (!this.eventMap[eventName]) this.eventMap[eventName] = [] this.eventMap[eventName].push(callback) }, emit(eventName, payload) { this.eventMap[eventName]?.forEach(cb => cb(payload)) }, off(eventName, callback) { this.eventMap[eventName] = this.eventMap[eventName]?.filter(cb => cb !== callback) ?? [] } } export default EventBus
// A.js import EventBus from './eventBus' export default function A() { const foo = () => { EventBus.emit('refreshB') // 其余foo业务逻辑 } return <button onClick={foo}>触发foo</button> }
// B.js import { useState, useEffect } from 'react' import EventBus from './eventBus' export default function B() { const [refreshFlag, setRefreshFlag] = useState(0) useEffect(() => { const handleRefresh = () => setRefreshFlag(prev => prev + 1) EventBus.on('refreshB', handleRefresh) // 组件卸载时移除监听,避免内存泄漏 return () => EventBus.off('refreshB', handleRefresh) }, []) return <div>B组件当前渲染标记:{refreshFlag}</div> }
方案3:全局状态管理
如果项目已经接入Redux、Zustand、Jotai等全局状态管理工具,可以直接在全局存储中定义刷新标记,A组件修改标记,B组件订阅标记,逻辑和状态提升方案一致,仅状态存储位置改为全局。
注意:非必要不要使用
forceUpdate等强制重渲染API,容易引发不可预期的副作用,优先通过状态变更驱动组件更新。
内容的提问来源于stack exchange,提问作者Gustavo
相关产品推荐
相关产品推荐

