React로 무한 스크롤을 구현하는 방법을 찾고 있습니다. 나는이 건너 반응 – 무한 스크롤을 하고 비효율적이 바로 DOM에 노드를 추가하고 제거하지 않는 한 발견했다. DOM에서 일정한 수의 노드를 추가, 제거 및 유지하는 React로 입증 된 솔루션이 있습니까?
다음은 jsfiddle 문제입니다. 이 문제에서는 한 번에 DOM에 50 개의 요소 만 갖고 싶습니다. 사용자가 위아래로 스크롤 할 때 다른 것들은로드되고 제거되어야합니다. 우리는 최적화 알고리즘 때문에 React를 사용하기 시작했습니다. 이제이 문제에 대한 해결책을 찾을 수 없습니다. 나는 airbnb infinite js 를 만났습니다 . 그러나 Jquery로 구현됩니다. 이 에어 비앤비 무한 스크롤을 사용하려면 내가하고 싶지 않은 React 최적화를 풀어야합니다.
스크롤을 추가하고 싶은 샘플 코드는 (여기에서는 모든 항목을로드하고 있습니다. 내 목표는 한 번에 50 개 항목 만로드하는 것입니다)
/** @jsx React.DOM */
var Hello = React.createClass({
render: function() {
return (<li>Hello {this.props.name}</li>);
}
});
var HelloList = React.createClass({
getInitialState: function() {
var numbers = [];
for(var i=1;i<10000;i++){
numbers.push(i);
}
return {data:numbers};
},
render: function(){
var response = this.state.data.map(function(contact){
return (<Hello name="World"></Hello>);
});
return (<ul>{response}</ul>)
}
});
React.renderComponent(<HelloList/>, document.getElementById('content'));
도움을 찾는 중 …
답변
기본적으로 스크롤 할 때 표시되는 요소를 결정한 다음 화면 밖의 요소를 나타 내기 위해 상단 및 하단에 단일 스페이서 요소를 사용하여 해당 요소 만 표시하도록 다시 렌더링하려고합니다.
Vjeux 는 여기서 볼 수있는 바이올린을 만들었습니다 : jsfiddle .
스크롤하면 실행됩니다.
scrollState: function(scroll) {
var visibleStart = Math.floor(scroll / this.state.recordHeight);
var visibleEnd = Math.min(visibleStart + this.state.recordsPerBody, this.state.total - 1);
var displayStart = Math.max(0, Math.floor(scroll / this.state.recordHeight) - this.state.recordsPerBody * 1.5);
var displayEnd = Math.min(displayStart + 4 * this.state.recordsPerBody, this.state.total - 1);
this.setState({
visibleStart: visibleStart,
visibleEnd: visibleEnd,
displayStart: displayStart,
displayEnd: displayEnd,
scroll: scroll
});
},
그러면 render 함수는 범위의 행만 표시합니다 displayStart..displayEnd
.
ReactJS : Modeling Bi-Directional Infinite Scrolling에 관심이있을 수도 있습니다 .
답변
React Infinite 라이브러리를 확인하십시오.
https://github.com/seatgeek/react-infinite
2016 년 12 월 업데이트
실제로 최근 많은 프로젝트에서 react-virtualized 를 사용하고 있으며 대부분의 사용 사례를 훨씬 더 잘 다루고 있습니다. 두 라이브러리 모두 훌륭하며 정확히 무엇을 찾고 있는지에 따라 다릅니다. 예를 들어 react-virtualized는라는 HOC를 통해 가변 높이 JIT 측정을 지원합니다 ( CellMeasurer
예 : https://bvaughn.github.io/react-virtualized/#/components/CellMeasurer) .
2018 년 11 월 업데이트
react-virtualized에서 얻은 많은 교훈 은 동일한 작성자 의 더 작고 빠르며 효율적인 react-window 라이브러리 로 이식되었습니다 .
답변
import React, { Component } from 'react';
import InfiniteScroll from 'react-infinite-scroller';
const api = {
baseUrl: '/joblist'
};
class Jobs extends Component {
constructor(props) {
super(props);
this.state = {
listData: [],
hasMoreItems: true,
nextHref: null
};
}
fetchData(){
var self = this;
var url = api.baseUrl;
if(this.state.nextHref) {
url = this.state.nextHref;
}
fetch(url)
.then( (response) => {
return response.json() })
.then( (json) => {
var list = self.state.listData;
json.data.map(data => {
list.push(data);
});
if(json.next_page_url != null) {
self.setState({
nextHref: resp.next_page_url,
listData: list
});
} else {
self.setState({
hasMoreItems: false
});
}
})
.catch(error => console.log('err ' + error));
}
}
componentDidMount() {
this.fetchData();
}
render() {
const loader = <div className="loader">Loading ...</div>;
let JobItems;
if(this.state.listData){
JobItems = this.state.listData.map(Job => {
return (
<tr>
<td>{Job.job_number}</td>
<td>{Job.title}</td>
<td>{Job.description}</td>
<td>{Job.status}</td>
</tr>
);
});
}
return (
<div className="Jobs">
<div className="container">
<h2>Jobs List</h2>
<InfiniteScroll
pageStart={0}
loadMore={this.fetchData.bind(this)}
hasMore={this.state.hasMoreItems}
loader={loader}>
<table className="table table-bordered">
<thead>
<tr>
<th>Job Number</th>
<th>Title</th>
<th>Description</th>
<th>Status</th>
</tr>
</thead>
<tbody>
{JobItems}
</tbody>
</table>
</InfiniteScroll>
</div>
</div>
);
}
}
export default Jobs;