如何使无限滚动获取功能按顺序工作
How to make infinite scroll fetch function work in order
我想无限滚动来获取任何项目,简单的步骤是:
1) 在屏幕末尾滚动。
2) 使用 redux 更新项目 pageIndex。
3) 使用 componentDidUpdate
捕捉这个 redux 动作。
4) 将获取的项目追加到项目数组的末尾。
class InfiniteScroll extends React.Component {
componentDidMount() {
window.addEventListener("scroll", throttle(this.onScroll, 500), false);
}
componentWillUnmount() {
window.removeEventListener("scroll", this.onScroll, false);
}
componentDidUpdate(preProps) {
if (props.pageindex === preProps.pageindex + 1)
fetchItems(...);
}
onScroll = () => {
if (
window.innerHeight + window.scrollY >=
document.body.offsetHeight - 100
) {
updatePage(...);
}
};
render() {
return <Component {...this.props} />;
}
}
这段代码唯一的问题是当updatePage
执行一次时,fetchItems
不能立即执行。
如果我是你,我会使用图书馆来为我完成繁重的工作。
一个选项是react-infinite-scroller。
以下是您的用例可能的样子,主要是伪代码:
<InfiniteScroll
pageStart={0}
loadMore={fetchItems} // that's your method for loading more results
hasMore={props.pageindex === preProps.pageindex + 1} // your 'has more' logic
loader={<div className="loader">Loading ...</div>}
>
{items} // <-- This is the content you want to load
</InfiniteScroll>
举个例子,check out the demo in their repo。
另一种选择是尝试调试您的代码。但是您需要提供更多上下文。从你提供的信息来看,真的很难判断问题出在哪里。
由于您使用的是 redux,因此您的项目列表应通过 actions/reducer 控制。
InfiniteScroll.js:
onScroll () {
var nearBottom = window.innerHeight + window.scrollY >= document.body.offsetHeight - 100;
if (!this.props.fetching && nearBottom) {
fetchItems(); // dispatch action
}
}
render () {
var items = this.props.items.map(item => (<Component {item}/>)
return (
<ul>{ items }</ul>
)
}
componentDidMount() {
window.addEventListener("scroll", this.onScroll.bind(this), false);
}
componentWillUnmount() {
window.removeEventListener("scroll", this.onScroll.bind(this), false);
}
操作:
fetchItems () {
return dispatch => {
dispatch({
type: "FETCH_ITEMS"
});
fetch("/api/items")
.then(items => {
dispatch(itemsReceived(items));
});
}
}
itemsReceived (items) {
return {
type: "ITEMS_RECEIVED",
payload: {
items: items
}
}
}
减速器:
case "FETCH_ITEMS":
return {
...prevState,
fetching: true
case "ITEMS_RECEIVED":
return {
...prevState,
fetching: false,
items: prevState.items.concat(items)
}
这样,一个明确定义的动作(FETCH_ITEMS)被滚动触发。使用 redux-thunk
,该操作会调用 API 来获取新项目。该调用完成后,您将分派一个新操作以通过减速器提供新项目。
reducer 然后更新状态,导致 <InfiniteScroll>
使用更新的项目列表重新呈现。
注意:如果出现错误,您还应该将抓取设置为 false。
我想无限滚动来获取任何项目,简单的步骤是:
1) 在屏幕末尾滚动。
2) 使用 redux 更新项目 pageIndex。
3) 使用 componentDidUpdate
捕捉这个 redux 动作。
4) 将获取的项目追加到项目数组的末尾。
class InfiniteScroll extends React.Component {
componentDidMount() {
window.addEventListener("scroll", throttle(this.onScroll, 500), false);
}
componentWillUnmount() {
window.removeEventListener("scroll", this.onScroll, false);
}
componentDidUpdate(preProps) {
if (props.pageindex === preProps.pageindex + 1)
fetchItems(...);
}
onScroll = () => {
if (
window.innerHeight + window.scrollY >=
document.body.offsetHeight - 100
) {
updatePage(...);
}
};
render() {
return <Component {...this.props} />;
}
}
这段代码唯一的问题是当updatePage
执行一次时,fetchItems
不能立即执行。
如果我是你,我会使用图书馆来为我完成繁重的工作。
一个选项是react-infinite-scroller。
以下是您的用例可能的样子,主要是伪代码:
<InfiniteScroll
pageStart={0}
loadMore={fetchItems} // that's your method for loading more results
hasMore={props.pageindex === preProps.pageindex + 1} // your 'has more' logic
loader={<div className="loader">Loading ...</div>}
>
{items} // <-- This is the content you want to load
</InfiniteScroll>
举个例子,check out the demo in their repo。
另一种选择是尝试调试您的代码。但是您需要提供更多上下文。从你提供的信息来看,真的很难判断问题出在哪里。
由于您使用的是 redux,因此您的项目列表应通过 actions/reducer 控制。
InfiniteScroll.js:
onScroll () {
var nearBottom = window.innerHeight + window.scrollY >= document.body.offsetHeight - 100;
if (!this.props.fetching && nearBottom) {
fetchItems(); // dispatch action
}
}
render () {
var items = this.props.items.map(item => (<Component {item}/>)
return (
<ul>{ items }</ul>
)
}
componentDidMount() {
window.addEventListener("scroll", this.onScroll.bind(this), false);
}
componentWillUnmount() {
window.removeEventListener("scroll", this.onScroll.bind(this), false);
}
操作:
fetchItems () {
return dispatch => {
dispatch({
type: "FETCH_ITEMS"
});
fetch("/api/items")
.then(items => {
dispatch(itemsReceived(items));
});
}
}
itemsReceived (items) {
return {
type: "ITEMS_RECEIVED",
payload: {
items: items
}
}
}
减速器:
case "FETCH_ITEMS":
return {
...prevState,
fetching: true
case "ITEMS_RECEIVED":
return {
...prevState,
fetching: false,
items: prevState.items.concat(items)
}
这样,一个明确定义的动作(FETCH_ITEMS)被滚动触发。使用 redux-thunk
,该操作会调用 API 来获取新项目。该调用完成后,您将分派一个新操作以通过减速器提供新项目。
reducer 然后更新状态,导致 <InfiniteScroll>
使用更新的项目列表重新呈现。
注意:如果出现错误,您还应该将抓取设置为 false。