我正在使用typescript构建一个react应用程序。
我想创建按钮,滚动到我的主页子组件的标题。
我在子组件中创建了一个ref,遵循this stack overflow应答并(试图)使用forward refs在父组件上访问它。
export class Parent extends Component {
private testTitleRef!: RefObject<HTMLHeadingElement>;
scrollToTestTitleRef = () => {
if (this.testTitleRef.current !== null) {
window.scrollTo({
behavior: "smooth",
top: this.testTitleRef.current.offsetTop
});
}
};
render() {
return <Child ref={this.testTitleRef} />
}
}
interface Props {
ref: RefObject<HTMLHeadingElement>;
}
export class Child extends Component<Props> {
render() {
return <h1 ref={this.props.ref}>Header<h1 />
}
}
不幸的是,当我触发
scrollToTestTitleRef
时,我得到错误:Cannot read property 'current' of undefined
表示ref未定义。为什么?我做错什么了?
编辑:
Estus帮助我创建ref。但是当我触发
scrollToTestTitleRef()
事件时,它不会滚动。当我得到输出时:
{"props":{},"context":{},"refs":{},"updater":{},"jss":{"id":1,"version":"9.8.7","plugins":{"hooks":{"onCreateRule":[null,null,null,null,null,null,null,null,null,null,null,null],"onProcessRule":[null,null,null],"onProcessStyle":[null,null,null,null,null,null],"onProcessSheet":[],"onChangeValue":[null,null,null],"onUpdate":[null]}},"options":{"plugins":[{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{}]}},"sheetsManager":{},"unsubscribeId":null,"stylesCreatorSaved":{"options":{"index":-99999999945},"themingEnabled":false},"sheetOptions":{},"theme":{},"_reactInternalInstance":{},"__reactInternalMemoizedUnmaskedChildContext":{"store":{},"storeSubscription":null},"state":null}
注意:我删除了
console.log
,this.testTitleRef.current
和cacheClasses
,因为它们包含循环依赖项。所以current似乎没有
_reactInternalFiber
键。这是否与在我的实际应用程序中,子组件被包装在材质ui的__reactInternalMemoizedMaskedChildContext
和react redux'offsetTop
中有关? 最佳答案
!
非空断言操作符可以抑制实际问题。在javascript/typescript中,无法将testTitleRef
属性指定为<Child ref={this.titleRef} />
,因此它保持未定义状态(也与testTitleRef
和titleRef
不一致)。
应该是这样的:
private testTitleRef: React.createRef<HTMLHeadingElement>();
scrollToTestTitleRef = () => {
if (!this.testTitleRef.current) return;
window.scrollTo({
behavior: "smooth",
top: this.testTitleRef.current.getBoundingClientRect().top + window.scrollY
});
};
render() {
return <Child scrollRef={this.testTitleRef} />
}
和
export class Child extends Component<Props> {
render() {
return <h1 ref={this.props.scrollRef}>Header<h1 />
}
}