如何在组件安装后运行 setInterval 并在 props 更新后重新运行它?



https://codepen.io/Fadeoc/pen/KvVExP?editors=1111

这是我在代码笔中的代码。

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 的新手,所以我想到的都是设置一个"样式"状态,计算组件中的偏移量,然后重新设置状态,所以 react 会再次渲染。

它工作正常,直到我发现两个问题。

第一个问题是我想通过 websocket 数据更新这个列表,我认为"它会随着道具的变化而重新渲染,因此状态也发生了变化",但它搞砸了第二个问题,似乎是我让这个自动滚动部分的方式错误。

如您所知,组件通常通过每个状态渲染一次,但在这种情况下,我可能设置状态的次数太多,每 20 毫秒,我担心性能。

每次从 websocket 服务器推送后,列表确实会变成一个新的列表,但它会停止自动滚动。

总结一下:

1 "每 20 毫秒设置一次状态以执行自动滚动"不好吗?

2 为什么通过道具更新后它会停止自动滚动? 我应该使用组件DidUpdate吗?但是这种生命周期方法会弄乱自动滚动,因为它经常运行。

  1. 我不确定每 20 毫秒自动滚动一次是好是坏,但在我看来,只有当更多项目添加到您的列表中时,才应该进行滚动。不确定触发 Web 套接字获取的频率(我不精通 Web 套接字(。

  2. 我猜你想在改变道具时自动滚动。为此,理想的组件事件是具有nextProps(新道具本身(的ComponentWillReceiveProps。您可以将当前道具与下一个道具进行比较,看看是否有任何变化,如果是,则启动滚动操作。

例:

ComponentWillReceiveProps(nextProps){
if (this.props.myName !== nextProps.myName) {
// do the code
}
}

最新更新