React点击触发事件后在另一组件渲染同一组件不同实例的实现问题
解决方案
你不需要跨组件主动获取smallView内的AbcComp实例,仅需要给fullView内的AbcComp传入和smallView内一致的btnProps属性,就能渲染出完全相同的实例效果。如果确实需要获取实例本身(比如调用实例内部方法/属性),可以配合Context做ref共享,两种场景的实现方式如下:
场景1:仅需要渲染相同样式的AbcComp(最常用,满足绝大多数需求)
- AbcComp.jsx 不需要修改,保持原有逻辑即可。
- smallViewComponent.jsx 修正原有语法错误后的代码:
import AbcComp from './..' class SmallViewComponent extends React.Component { state = { cmpInstance: ['component1','component2','component3'] } render (){ return ( <div> {this.state.cmpInstance.map((e) => <AbcComp key={e} btnProps={e}/> )} </div> ) } }
- fullViewComponent.jsx 新增state存储当前选中的实例标识,点击按钮时更新标识并传入AbcComp:
import AbcComp from './..' // 建议把实例列表抽成公共常量,两个组件统一引入,避免重复维护 const CMP_LIST = ['component1','component2','component3'] class FullViewComponent extends React.Component { state = { currentCmpKey: null } loadInstance = () => { const selectedKey = CMP_LIST[Math.floor(Math.random() * CMP_LIST.length)] this.setState({ currentCmpKey: selectedKey }) } render (){ return ( <div> <button onClick={this.loadInstance}>切换实例</button> {/* 传入选中的标识即可渲染对应样式的AbcComp */} {this.state.currentCmpKey && <AbcComp btnProps={this.state.currentCmpKey} />} </div> ) } }
场景2:需要获取AbcComp的实例对象(调用实例内部方法/属性)
如果需要拿到实例本身,通过React Context共享ref即可:
- 新增公共Context文件
CmpContext.js:
import { createContext } from 'react' export const CmpContext = createContext()
- 在两个组件的公共父组件内注入Context,统一存储所有实例ref:
import { CmpContext } from './CmpContext' import SmallViewComponent from './smallViewComponent' import FullViewComponent from './fullViewComponent' class ParentComponent extends React.Component { state = { cmpRefs: {} } saveCmpRef = (key, ref) => { this.setState(prev => ({ cmpRefs: { ...prev.cmpRefs, [key]: ref } })) } render() { return ( <CmpContext.Provider value={{ cmpRefs: this.state.cmpRefs, saveCmpRef: this.saveCmpRef }}> <SmallViewComponent /> <FullViewComponent /> </CmpContext.Provider> ) } }
- 修改smallViewComponent.jsx,给每个AbcComp挂载ref并存入Context:
import AbcComp from './..' import { CmpContext } from './CmpContext' const CMP_LIST = ['component1','component2','component3'] class SmallViewComponent extends React.Component { static contextType = CmpContext render (){ return ( <div> {CMP_LIST.map((e) => <AbcComp key={e} btnProps={e} ref={(ref) => this.context.saveCmpRef(e, ref)} /> )} </div> ) } }
- 修改fullViewComponent.jsx,点击按钮时即可从Context中获取对应实例:
import AbcComp from './..' import { CmpContext } from './CmpContext' const CMP_LIST = ['component1','component2','component3'] class FullViewComponent extends React.Component { static contextType = CmpContext state = { currentCmpKey: null } loadInstance = () => { const selectedKey = CMP_LIST[Math.floor(Math.random() * CMP_LIST.length)] this.setState({ currentCmpKey: selectedKey }) // 这里可以拿到smallView中对应的AbcComp实例 const targetInstance = this.context.cmpRefs[selectedKey] console.log('获取到的实例:', targetInstance) } render (){ return ( <div> <button onClick={this.loadInstance}>切换实例</button> {this.state.currentCmpKey && <AbcComp btnProps={this.state.currentCmpKey} />} </div> ) } }
内容的提问来源于stack exchange,提问作者Ahmad
相关产品推荐
相关产品推荐

