The simplest way to make a pull-to-refresh and infinite tableview with ReactJS
Pull-to-refresh and pull-to-load-more are extremely common to show data in web, there are so many libraries to make it in React, but there are some problems.š©
- Most of them are difficult to subclass, you need to use their component to render the cells. It is quite troublesome if you want to add more actions in you cells.
- The refresh libraries and infinite ones are usually separate, you have to integrate those libraries and change them to make them same style for your web.
- Some of them are quite bulky or you even have to include extra dependencies.
As a react beginner, the first question come up in my mind isā¦are those necessary?š¤
OKā¦then what are necessary in such tableview?
- Subscribe the scroll to top & bottom events
- Refresh/load more content
- Insert loading indicators
- Dismiss loading indicators once new data received
Well..how about make it on my own???
Scroll to top & bottom events
Thanks Google, there are some DOM properties, scrollTop, clientHeight and scrollHeight, should be enough to detect the scroll-to-up & scroll-to-bottom events, letās use it in the onScroll event.
var scrollviewOffsetY = dom.scrollTop
var scrollviewFrameHeight = dom.clientHeight
var scrollviewContentHeight = dom.scrollHeight
var sum = scrollviewOffsetY+scrollviewFrameHeightif (sum <= scrollviewFrameHeight) {
// the top reached
} else if (sum >= scrollviewContentHeight) {
// the bottom reached
}
Refresh & load-more data
Thanks Facebook, it is easy to be done in React. The scrollview just needs to tell its parent that it needs new data via props.
In tableview component
this.props.onScrollToTop
In its parent
// inside render()<ExampleTableView
dataSource={this.state.data}
onScrollToTop={this.handleScrollToTop}
/>// custom methodhandleScrollToTop() {
// refresh
myRefreshMethod(function() {
this.setState({data: data})
}.bind(this))
}
Actually, it is basically done !!! It will refresh/load-more data when I pull up/down. BUT my users wonāt know it becauseā¦there isnāt any indicators showing to my users that it is loadingā¦
Insert loading indicators
There are at least two ways to do it, insert the indicators via DOM API or render the indicators via ReactDOM.
via DOM API
var refreshIndicator = document.createElement(ādivā)
refreshIndicator.className = "spinner"var tableview = document.getElementById("myTableview");
tableview.insertBefore(refreshIndicator, tableview.firstChild)
via ReactDOM
render() {return (
<div className=āmyTableviewā onScroll={this.viewDidScroll}>
{this.refreshIndicator()}
{cells}
</div>
)
}refreshIndicator() {
if (this.state.isRefreshing) {
return (
<div className=āspinnerā>šā¦</div>
)
}
return
}
Dismiss loading indicators once new data received
Well, if you inserted elements via DOM API, letās try using callback in parent to tell the tableview to dismiss the loading indicators.
in parent
handleScrollToTop(refreshCompleted) {
// refresh
myRefreshMethod(function() {
refreshCompleted()
this.setState({data: data})
}.bind(this))
}
in tableview
this.props.onScrollToTop(function() {
// dismiss my spinner here
var tableView = document.getElementById(tableViewIdName)
var firstChild = tableView.firstChild
if (firstChild.className.indexOf("spinner") > -1) {
tableView.removeChild(firstChild)
}}.bind(this))
If you render your indicators via ReactDOM, letās declare a state āisRefreshingā, assign the states once data received and React will automagically do it for you.
refreshIndicator() {
if (this.state.isRefreshing) {
return (
<div className=āspinnerā>šā¦</div>
)
}
return
}
Whatās next?
NOTHING !!! IT IS ALL DONE !!!
Source code?
If you wanna know more about the implementation, please checkout my repo.
You can also try out the ready-to-use package to enable pull-to-refresh and infinite in your own scrollview in a minute.š