当道具在反应虚拟化中发生变化时如何滚动到底部?
How to scroll to bottom when props changed in react-virtualized?
我有来自 react-virtualized 库的带有 List 的组件 App。
我需要在初始渲染时将我的列表滚动到底部。
我做到了,添加了 scrollToIndex 选项。但是当我在我的列表数组中添加新对象时,它不会滚动到我最后添加的对象。我该如何解决?使用 "forceUpdate()" 函数是好的解决方案吗?
import { List } from "react-virtualized";
import loremIpsum from 'lorem-ipsum';
const rowCount = 1000;
const listHeight = 600;
const rowHeight = 50;
const rowWidth = 800;
class App extends Component {
constructor() {
super();
this.renderRow = this.renderRow.bind(this);
this.list = Array(rowCount).fill().map((val, idx) => {
return {
id: idx,
name: 'John Doe',
image: 'http://via.placeholder.com/40',
text: loremIpsum({
count: 1,
units: 'sentences',
sentenceLowerBound: 4,
sentenceUpperBound: 8
})
}
});
}
handle = () => {
this.list = [...this.list, { id: 1001, name: "haha", image: '', text: 'hahahahahaha' }];
this.forceUpdate();
this.refs.List.scrollToRow(this.list.length);
};
renderRow({ index, key, style }) {
console.log('____________', this.list.length);
return (
<div key={key} style={style} className="row" >
<div className="image">
<img src={this.list[index].image} alt="" />
</div>
<div onClick={this.handle}>{this.state.a}</div>
<div className="content">
<div>{this.list[index].name}</div>
<div>{this.list[index].text}</div>
</div>
</div>
);
}
render() {
return (
<div className="App">
<div className="list">
<List
ref='List'
width={rowWidth}
height={listHeight}
rowHeight={rowHeight}
rowRenderer={this.renderRow}
rowCount={this.list.length}
overscanRowCount={3}
scrollToIndex={this.list.length}
/>
</div>
</div>
);
}
}
export default App;
您提到在更改列表项时需要滚动到底部,老实说我不喜欢使用 forceUpdate
。正如 React 文档中提到的:
Normally you should try to avoid all uses of forceUpdate() and only read from this.props and this.state in render().
幸运的是,React 生命周期方法之一适用于这种情况,它是调用 componentDidUpdate
。但是您需要对代码进行一些重构。我建议将其放在 state/props.
上,而不是使用私有字段
此方法将在更新 props/state 发生后立即调用。但是,初始渲染不会调用此方法。
你需要做的是,对比道具,是换还是不换?然后调用 this.refs.List.scrollToRow(this.list.length);
示例代码
class App extends Component {
constructor() {
this.state = {
list: [] // put your list data here
}
}
// Check the change of the list, and trigger the scroll
componentDidUpdate(prevProps, prevState) {
const { list } = this.state;
const { list: prevList } = prevState;
if (list.length !== prevList.length) {
this.refs.List.scrollToRow(list.length);
}
}
render() {
// usual business
}
}
React 生命周期方法的更多参考:
https://reactjs.org/docs/react-component.html#componentdidupdate
我有来自 react-virtualized 库的带有 List 的组件 App。 我需要在初始渲染时将我的列表滚动到底部。
我做到了,添加了 scrollToIndex 选项。但是当我在我的列表数组中添加新对象时,它不会滚动到我最后添加的对象。我该如何解决?使用 "forceUpdate()" 函数是好的解决方案吗?
import { List } from "react-virtualized";
import loremIpsum from 'lorem-ipsum';
const rowCount = 1000;
const listHeight = 600;
const rowHeight = 50;
const rowWidth = 800;
class App extends Component {
constructor() {
super();
this.renderRow = this.renderRow.bind(this);
this.list = Array(rowCount).fill().map((val, idx) => {
return {
id: idx,
name: 'John Doe',
image: 'http://via.placeholder.com/40',
text: loremIpsum({
count: 1,
units: 'sentences',
sentenceLowerBound: 4,
sentenceUpperBound: 8
})
}
});
}
handle = () => {
this.list = [...this.list, { id: 1001, name: "haha", image: '', text: 'hahahahahaha' }];
this.forceUpdate();
this.refs.List.scrollToRow(this.list.length);
};
renderRow({ index, key, style }) {
console.log('____________', this.list.length);
return (
<div key={key} style={style} className="row" >
<div className="image">
<img src={this.list[index].image} alt="" />
</div>
<div onClick={this.handle}>{this.state.a}</div>
<div className="content">
<div>{this.list[index].name}</div>
<div>{this.list[index].text}</div>
</div>
</div>
);
}
render() {
return (
<div className="App">
<div className="list">
<List
ref='List'
width={rowWidth}
height={listHeight}
rowHeight={rowHeight}
rowRenderer={this.renderRow}
rowCount={this.list.length}
overscanRowCount={3}
scrollToIndex={this.list.length}
/>
</div>
</div>
);
}
}
export default App;
您提到在更改列表项时需要滚动到底部,老实说我不喜欢使用 forceUpdate
。正如 React 文档中提到的:
Normally you should try to avoid all uses of forceUpdate() and only read from this.props and this.state in render().
幸运的是,React 生命周期方法之一适用于这种情况,它是调用 componentDidUpdate
。但是您需要对代码进行一些重构。我建议将其放在 state/props.
此方法将在更新 props/state 发生后立即调用。但是,初始渲染不会调用此方法。
你需要做的是,对比道具,是换还是不换?然后调用 this.refs.List.scrollToRow(this.list.length);
示例代码
class App extends Component {
constructor() {
this.state = {
list: [] // put your list data here
}
}
// Check the change of the list, and trigger the scroll
componentDidUpdate(prevProps, prevState) {
const { list } = this.state;
const { list: prevList } = prevState;
if (list.length !== prevList.length) {
this.refs.List.scrollToRow(list.length);
}
}
render() {
// usual business
}
}
React 生命周期方法的更多参考:
https://reactjs.org/docs/react-component.html#componentdidupdate