我具有以下父/子组件。最初渲染Child组件后,我需要滚动到顶部。
import React, {Component} from 'react';
import Child from "./Child";
class Parent extends Component {
render() {
return (
<div>
<div ref={topDiv => {
this.topDiv = topDiv;
}}/>
<Child
topDiv={this.topDiv}
/>
</div>
);
}
}
export default Parent;
import React, {Component} from 'react';
class Child extends Component {
componentDidMount() {
this.scrollToTop();
}
// componentWillReceiveProps(nextProps, nextContext) {
// nextProps.topDiv.scrollIntoView();
// }
scrollToTop() {
this.props.topDiv.scrollIntoView();
}
render() {
return (
<div style={{height: '500rem'}}>
Long Child
</div>
);
}
}
export default Child;
使用此方法,我收到错误消息:
TypeError:无法读取未定义的属性'scrollIntoView'
我认为这是因为调用componentDidMount
时还没有收到道具,所以topDiv
为空/未定义。
如果我使用componentWillReceiveProps
,如注释部分所示,则可以正常工作。但由于以下原因,我无法使用它:
1.已弃用。
2.我认为每次收到道具时都会调用它。因此,我想我需要保留一个变量以了解是否是第一次收到道具?
我不能使用componentDidUpdate
,因为documentation表示“ 初始渲染未调用此方法。”。
渲染组件后首次收到道具时该怎么做?
答案 0 :(得分:1)
绝对应该在componentDidMount
中提供道具。
这似乎可能是由于React生命周期中有些混乱。
在您的父母中,大约在安装Child
的同时,在渲染器中提供了ref回调。根据{{3}}:
React将在组件装入时使用DOM元素调用ref回调,而在组件卸载时使用null进行调用。保证在componentDidMount或componentDidUpdate触发之前,引用是最新的。
但是,componentDidMount
个孩子将在其父母componentDidMount
之前解雇,因此,这种保证并不意味着Parent
的{{1}}将在{ {1}}呼叫this.topDiv
。 (而且,进一步考虑,它绝对不保证在作为道具提供给Child
之前会被定义。)
在您的父母中,您可以尝试类似的
componentDidMount
这将确保在安装Child
之前设置您的参考。 componentDidMount() {
this.setState({ divSet: true });
}
render() {
let child = null;
if (this.state.divSet) {
child = <Child topDiv={this.topDiv} />
}
return (
<div>
<div ref={topDiv => {
this.topDiv = topDiv;
}}/>
{child}
</div>
);
}
专门用于在设置ref时强制父级重新呈现。
答案 1 :(得分:1)
根据定义,您正在尝试做的事情是不可能的!当你说
我需要在子组件最初开始时滚动到顶部 呈现。
您是说父母的右上角吗?
但是这里的关键细节是
您的孩子完成渲染后,您的父母尚未 被渲染!没有顶部可以滚动到Yet !!
组件的生命周期
这是组件的典型生命周期流
当涉及到亲子关系时
还简要说明了新添加的生命周期方法,代替了componenWillRecieveProps
getDerivedStateFromProps(道具,状态)
getDerivedStateFromProps在调用渲染之前被调用 初始安装和后续更新上的方法。这应该 返回一个对象以更新状态,或者返回null则不更新任何内容。
所以最好的选择是在不被允许的情况下调用滚动条 组件componentDidMount,您可以在其中访问其引用。
如果仍然确定要在子组件中执行此操作,则必须将 getDerivedStateFromProps 与状态标记结合使用,以检测您是否已至少滚动到顶部一次。总体上来说这可能有点效率和肮脏。
请查看here,以获取组件生命周期的凉爽流程图,以了解其清晰性!
答案 2 :(得分:0)
将this.scrollToTop
绑定到constructor
中的类组件:
class Child extends Component {
constructor() {
this.scrollToTop = this.scrollToTop.bind(this);
}
...rest of your component code