https://codepen.io/Fadeoc/pen/KvVExP?editors=1111
这是我在Codepen中的代码。
let jsonData = {
value: [1,2,3,4,5,6,7,8,9,10]
}
class Father extends React.Component {
constructor(props) {
super(props);
this.state = {
data: jsonData,//data from websocket
}
}
render() {
const arr = this.state.data.value;
return (
<Child arr={arr} />
);
}
}
class Child extends React.Component {
constructor(props) {
super(props);
this.state = {
style: null,
arr: this.props.arr
};
}
getNodePositionBottom(ref) {
const nodeY = ReactDOM.findDOMNode(ref).getBoundingClientRect().bottom;
return nodeY;
}
getNodePositionTop(ref) {
const nodeY = ReactDOM.findDOMNode(ref).getBoundingClientRect().top;
return nodeY;
}
componentDidMount() {
const divBottom = this.getNodePositionBottom(this.div);
const divTop = this.getNodePositionTop(this.div);
const height = divBottom - divTop;
const ulBottom = this.getNodePositionBottom(this.ul);
const ulTop = this.getNodePositionTop(this.ul);
const heightUL = ulBottom - ulTop;
if (ulBottom > divBottom) {
this.scrollingTop = setInterval(
function(){
this.offsetY = this.offsetY || 0;
if (ulBottom > divTop && this.offsetY + heightUL!== 0) {
this.offsetY -= 1;
this.setState({
style: {top: + this.offsetY + "px"}
});
} else {
this.setState({
style: {top: height + "px"}
});
this.offsetY = height;
}
}.bind(this),
20
);
}
}
render() {
const arr = this.state.arr;
let arrList = arr.map((name, i) => <li key={i} className="list">{name}</li>);
return (
<div ref={(div) => {this.div = div}} className="father">
<ul ref={(ul) => {this.ul = ul}} className="child" style={this.state.style}>
{arrList}
</ul>
</div>
);
}
}
ReactDOM.render(<Father />, document.getElementById("app"));
如果列表高度高于容器,我正在尝试构建一个在渲染后自动滚动到上面的列表。通过websocket数据更新列表成员,在每个websocket消息之后,更新列表成员,并再次比较高度以确定是否自动滚动。
我是React的新手,所以我想到的一切都是&#34;风格&#34; state,计算组件中的偏移量,并重新设置状态,因此react将再次渲染。
它工作正常,直到我发现两个问题。
第一个问题是我想通过websocket数据更新这个列表,我认为&#34;它会在道具发生变化的情况下重新渲染,因此状态也发生了变化,但是第二个问题很糟糕,这似乎是我使这个自动滚动部分错误的方式。
如你所知,组件通常会在每个状态下渲染一次,但在这种情况下,我可能会设置状态太多次,每20毫秒,我担心性能。
每次从websocket服务器推送后,列表都会变为新列表,但会停止自动滚动。
总结一下:
1是&#34;每20毫秒设置一次状态以执行自动滚动&#34;坏?
2为什么它会在通过道具更新后停止自动滚动?我应该使用componentDidUpdate吗?但是这个生命周期方法会因为它经常运行而混乱自动滚动。
答案 0 :(得分:1)
我不确定每20ms的自动滚动是好还是坏,但在我看来,只有在列表中添加了更多项目时才会滚动。不确定触发Web套接字的频率是多少(我不熟悉Web套接字)。
我想你想在改变道具时自动滚动。为此,理想的组件事件是ComponentWillReceiveProps
,其中包含nextProps(新道具本身)。您可以将当前道具与下一个道具进行比较以查看是否有任何更改,如果是,则启动滚动操作。
示例:
ComponentWillReceiveProps(nextProps){
if (this.props.myName !== nextProps.myName) {
// do the code
}
}