React中模拟自定义组件点击遇TypeError,求助解决方法
解决React Refs调用
.click()报错的问题 首先,你遇到的问题很明确:你通过refs获取到的是InterestBox组件的实例,而不是实际的DOM元素,所以直接调用.click()会报错——因为React组件实例本身没有这个DOM方法。下面给你两种可行的解决方案,结合你的代码修改:
方案1:在子组件中暴露触发点击的方法
这是最符合React组件设计思路的方式,通过让子组件暴露一个公共方法,父组件调用这个方法来模拟点击:
步骤1:修改InterestBox组件,添加触发方法
在InterestBox类中新增一个triggerClick方法,内部直接调用已有的handleClick逻辑:
export class InterestBox extends Component { // ... 其他已有代码 // 新增方法:供父组件调用以触发点击 triggerClick() { this.handleClick(); } // ... 其他已有代码 }
步骤2:在InterestList中调用组件实例的方法
把原来的pinterest.click()替换为pinterest.triggerClick()即可:
componentDidUpdate(prevProps) { // ... 其他已有代码 if(this.props.alreadyChecked != prevProps.alreadyChecked) { this.props.alreadyChecked.forEach((item) => { this.pinterestRefs.current.forEach((pinterest) => { if(item == pinterest.props.id) { console.log(pinterest) // 替换为组件暴露的方法 pinterest.triggerClick(); } }) }) } // ... 其他已有代码 }
方案2:直接获取子组件内的DOM元素引用
如果你更想直接操作DOM元素,可以修改refs的传递逻辑,让父组件拿到InterestBox内部的点击DOM元素:
步骤1:修改InterestBox组件,传递内部DOM的ref
在InterestBox中创建一个指向点击元素的ref,并通过props接收父组件的ref来传递:
export class InterestBox extends Component { constructor(props) { super(props); // ... 其他已有代码 this.contentRef = React.createRef(); // 指向实际点击的div } componentDidMount() { // 把内部DOM的ref传递给父组件的ref if (this.props.innerRef) { this.props.innerRef.current = this.contentRef.current; } } // ... 其他已有代码 render() { return ( <div className="column is-one-fifth-desktop is-half-touch"> <div className="interest-box"> <div className="interest-box-adjuster"> {/* 把ref绑定到这个div */} <div ref={this.contentRef} className={"interest-box-content " + (this.state.activated == true ? 'interest-box-activated' : '')} onClick={this.handleClick}> <img className="interest-icon" src={this.images[this.props.icon]} style={{'height': '50%'}}></img> <i className="activated-icon fas fa-check"></i> <span ref={"interest_text"} className="interest-text">{this.props.title}</span> </div> </div> </div> </div> ) } }
步骤2:修改InterestList的ref逻辑
把原来的ref={callbackRef}替换为innerRef={callbackRef},这样refs数组里就会存实际的DOM元素:
render() { return ( <React.Fragment> {Object.keys(this.state.pinterests).map((interest, i) => { var pinterest = this.state.pinterests[interest]; var callbackRef = node => this.pinterestRefs.current[i] = node; {/* 替换ref为innerRef */} return <InterestBox id={pinterest.id} onClick={this.props.onClick} icon={pinterest.picture_src} title={pinterest.name} innerRef={callbackRef} /> })} </React.Fragment> ) }
这样之后,你原来的pinterest.click()代码就可以正常工作了,因为现在pinterest是实际的DOM元素。
小提示
推荐优先使用方案1,因为直接操作DOM不符合React的声明式编程理念,而通过组件暴露方法的方式更符合组件间通信的规范,也更易于维护。
内容的提问来源于stack exchange,提问作者user11936976
相关产品推荐
相关产品推荐

