developerdizzle / react-virtual-list Goto Github PK
View Code? Open in Web Editor NEWSuper simple virtualized list React component
Home Page: http://developerdizzle.github.io/react-virtual-list/
License: MIT License
Super simple virtualized list React component
Home Page: http://developerdizzle.github.io/react-virtual-list/
License: MIT License
React 15.5 introduced another warnings, like using React.PropTypes (https://facebook.github.io/react/blog/2017/04/07/react-v15.5.0.html).
It's needed to fix these warnings.
I've spent some time trying to figure out why my react-virtual-list implementation kept scrolling down after I reached the bottom, seemingly increasing the list's size the further I scrolled. After I dug into how this library works, at some point it became really obvious what the problem was: With each list item vanishing above the viewport, more padding was added to the list, which in turn was added to the list's height because I hadn't set box-sizing: border-box
on it previously.
If this requirement was included somewhere in the readme, that might prevent some pain getting started. Otherwise, really good job with this!
There's a number of similar projects so it would be nice if readme.md helped people with choosing the project that's just right for them.
https://github.com/orgsync/react-list
https://github.com/nmn/react-infinity
https://github.com/seatgeek/react-infinite
https://github.com/bvaughn/react-virtualized
Pulled out my hair over this for more than an hour.
The container of the list MUST have "box-sizing: border-box;" set, or the padding will contribute to the container's height and the whole thing breaks down.
Would be nice if the lib injected this style or you mentioned it in the documentation. :)
If it helps my implementation looks like this:
this.list = VirtualList()(({
virtual,
itemHeight,
}) => (
<div style={{boxSizing: "border-box", ...virtual.style}}>
{virtual.items.map((prod, idx) => (
<div style={{height: itemHeight}} key={idx}>{new MenuItem(prod, this.state.menu.catTypes[prod.mainCategory as string], this.state.menu.locationOrdering).render()}</div>
))}
</div>
));
Below is the code which I'm using to integrate your component.
const MyList = ({
virtual,
itemHeight,
}) => (
item_${item.id}
} style={{height: 240}}>and after that I'm using 'MyVirtualList' inside my render.
<MyVirtualList items={onwFlightsCopy} itemHeight={240}/>
onwFlightsCopy is a huge list of react elements (>400).
I tried putting some debugger and found out my 'firstItemIndex' and 'lastItemIndex' is always coming as 0 and 1. Can you please let me know why this is being set faulty ?
Hi! I'am trying to add new elements at list, but added elements is not rendered.
In screenshot the result of render function with my refreshing list and virtual argument
const MyList = ({ virtual, itemHeight, section }) => {
console.log(virtual)
return (
<ListStyled>
{virtual.items.map((row, index) => (
<div key={index} style={{ display: 'flex'}}>
{row.map((material) => (
<MaterialListItem
key={material.get('id')}
material={material}
section={section}
/>
))}
</div>
))}
</ListStyled>
)};
splitIntoChunks = (list, chunkSize = 4) => {
return Range(0, list.count(), chunkSize)
.map(chunkStart => list.slice(chunkStart, chunkStart + chunkSize));
}
render() {
const items = this.splitIntoChunks(this.props.materials).toList().toArray()
console.log(items)
const MyVirtualList = this.MyVirtualList;
return (
<div>
<MyVirtualList
items={items}
itemHeight={130}
section={this.props.section}
/>
...
While server rendering the list with default state, the code breaks since window object is directly referenced in the condition for check for requestAnimationFrame.
Just a feature request, but any change there is a variable height component prop for this?
It may be borderline abuse, but I tried the example at http://developerdizzle.github.io/react-virtual-list/ with a million items, and it fails to render when I drag the scrollbar to the bottom. Know what would cause the failure?
We have a requirement to virtually scroll millions of items, so I could potentially help to write an improvement.
Latest Chrome on OSX.
Using this space to gather some best practices before incorporating into the official documentation.
slice
on their observables before using as the items
prop on the virtual component.initialState
for server-side renderingmapVirtualToProps
if you prefer to use other style rules (instead of paddingTop
), such as translateY
Is it possible to load in items upon different scroll events or something?
Hi,
Thanks for taking the time to write this module.
I'm trying to adapt your list component to my use-case; I'm trying to build a real-time data feed where new messages are prepended to the top of the list. Prepending is easy, I simply rebuild the list in your update function from the test example, and call setState().
But I would also like to maintain the scroll position so the list doesn't jitter while the user is reading. Basically, if the top-most box is currently visible in the viewport, then allow the render function to proceed (because the user is viewing the top of the list). If the user is scrolling somewhere further down the list, then don't render. The problem is I don't know how to check if the first item from the list is currently displayed in the DOM. Is there a way to extract the current set of items being rendered? How do I extract the "key={item.id}" from the rendered boxes?
Thanks!
The latest version of React (v0.14) throws a warning for react-virtual-list because it doesnt extend React.Component
Same issue as this
reduxjs/redux-devtools#100
Warning: VirtualList(...): React component classes must extend React.Component.
Hi there, the demo link on the readme pointing to the source is not working:
https://github.com/developerdizzle/react-virtual-list/blob/gh-pages/App.jsx
hi, I am using "version": "2.0.0"
did not have dist
dir
observable list
is not an array obj, when I use mobx
Warning: Failed prop type: Invalid prop `items` of type `object` supplied to `vlist`, expected `array`.
in vlist (created by News)
in News (created by inject-News-with-newsStore)
in inject-News-with-newsStore (created by Route)
in Route (created by Home)
in div (created by Home)
in Home (created by inject-Home-with-newsStore)
in inject-Home-with-newsStore (created by Route)
in Route (created by App)
in div (created by App)
in Router (created by HashRouter)
in HashRouter (created by App)
in App
in Provider
in AppContainer
i try filling 1,000,000 records and then i scroll down, its just can render about 400,000 records, do you thing that problem is because of padding-top is too big ?
First of all, very nice work, I like your virtual-list, it's very usefull and super efficient.
I just has a suggestion: have a way to force the rendering of the list, even if we don't scroll.
I'm using your list to show a big list of complex components. On each of this component I have a check box (to be able to select it and make later an action). Outside of the virtual-list, I have "select-all" button. When I click on it my items array is updated and all the items are marked as checked, but the Virtualist is not updated, because I didn't scroll it yet.
Is there a way to improve this?
Thanks
I have virtual list and I store selected row in component state. If selected row is changed, virtual list not rerender content, because metod shouldComponentUpdate compares only bufferStart, height and items equality, but I store selected item separately. Is there are any way to tell rerender virtual list component?
Thank you.
Currently only calculates item visibility against window object. Allow a container element to be specified in props, so that a scrollable div can be used as well.
I need to make the first visible item to have some predefined index. This is my code and it doesn't work, the first visible item always has index of zero
import React from 'react';
import VirtualList from 'react-virtual-list';
const List = ({ virtual, itemHeight }) => (
<ul style={virtual.style}>
{virtual.items.map(item => (
<li key={`item_${parseInt(item, 10)}`} style={{ height: itemHeight }}>
{item}
</li>
))}
</ul>
);
class Slides extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
slides: [
'00', '01', '02', '03', '04', '05', '06', '07', '08', '09',
'10', '11', '12', '13', '14', '15', '16', '17', '18', '19',
'20', '21', '22', '23', '24', '25', '26', '27', '28', '29',
],
};
const options = {
initialState: {
firstItemIndex: 10,
lastItemIndex : 20
}
};
this.ListSlides = VirtualList(options)(List);
}
render() {
const ListKtuviot = this.ListSlides;
return (
<ListKtuviot items={this.state.slides} itemHeight={50} />
);
}
}
Slides.propTypes = {};
export default Slides;
Currently, the highest supported version is react 15.
react-virtual-list/package.json
Lines 53 to 56 in 42dbd7d
Currently VirtualList attaches to the 'resize' event on the supplied container option.
This is fine when window
is supplied as the container, but will not fire when an alternate element is supplied.
There are a number of approaches for detecting element size change of non-window elements that could be integrated to correctly trigger this.refreshState
.
Happy to submit a PR if you wanted to choose which lib you liked best.
Hi, there should be some way how to animate List component using popular react-transition-group
(https://github.com/reactjs/react-transition-group). Can you try to create example for that?
getVirtualState
is getting the height of the container every onScroll
(in addition to a lot of other repeated calculations) when the values likely haven't changed. I believe this is causing elements to be reflowed by the browser, and even if not, is doing the same work over and over.
I will try to optimize the method after #14 which is required to know if things need to be recalculated.
Likely related to #1
compare, for example, code of setStateIfNeeded method (VirtualList.js) in lib and src directories.
the latest version in NPM repository (2.2.3) was also not re-built.
Related to #21. Right now, props.scrollDelay
is used to throttle the internal onScroll
handler.
The way I do this in my resize handlers is to use requestAnimationFrame
. They aren't necessarily mutually exclusive -- requestAnimationFrame
could be used on the debounced handler. This could improve perceived rendering performance significantly.
Right now the only dependency of the library is React, but I think it could be worthwhile to use chrisdickinson/raf or another polyfill here.
Experimenting with a new architecture as an HOC. I like this as it gives more control to the consumer. One question I've been thinking about is which options, if any, to use as HOC parameters vs properties?
// the HOC
import VirtualList from 'react-virtual-list';
// your component
const MyList = ({
virtual,
itemHeight,
}) => (
<ul style={virtual.style}>
{virtual.items.map((item) => (
<li key={`item${item.id}`} style={{height: itemHeight }}>
Lorem ipsum dolor sit amet
</li>
))}
</ul>
);
// using the HOC - which options, if any, should go in here?
const options = {
scrollThrottle: 1000,
};
const MyVirtualList = VirtualList(options)(MyList);
// rendering - which options should be props here?
<MyVirtualList
items={myBigListOfItems}
container={window}
itemBuffer={0}
itemHeight={100}
/>
VirutalList attempts to directly add the needed event listeners directly to the DOM element. I have found this can cause the error Cannot read property addEventListener of null
in certain cases, because componentDidMount
on the virtual list is being called before the parent has rendered.
Is there any obvious work-around for this or is there something wrong with our lifecycle management?
I'm back and finally have some free time this upcoming week, so I'll be tackling my other open issues and PRs. Sorry for the cruft!
npm install --save react react-dom
npm WARN unmet dependency ./node_modules/react-virtual-list requires react@'^0.13.3' but will load
npm WARN unmet dependency ./node_modules/react,
npm WARN unmet dependency which is version 0.14.0
Can be reproduced on http://developerdizzle.github.io/react-virtual-list/ by zooming in enough that windowed list isn't visible.
Right now, getVirtualState
is called in 4 places: getInitialState
, componentWillReceiveProps
, componentDidMount
, and onScroll
. If the window is resized, or the orientation changes on mobile, this causes the list to display too few or too many items, depending on the change.
A listener on the window for resize and orientation change events to call getVirtualState
would fix this (I do this my own wrapper for VirtualList in my application). I can PR if you're interested!
Hi,
you specified that items should be an array but since this is a mobx related module, it would probably make sense that observable lists can be passed as items as well (I'm currently getting error notices because of this)?
static propTypes = {
items: PropTypes.oneOfType([
PropTypes.array,
PropTypes.object
]).isRequired,
itemHeight: PropTypes.number.isRequired,
itemBuffer: PropTypes.number,
};
Right now, getInitialState
provides an empty array for state.items
because of this check.
While this makes sense in the context, the component must render twice (once after componentWillMount
with no items, and then again when the state changes when the calculated height is known on componentDidMount
). This causes a flash of the empty list beforehand, and also means that server side rendering doesn't work. What do you think of having a property to provide a number of items that will be rendered on the initial render, and then when componentDidMount
runs, rendered selectively as usual?
This way, it can render enough items to generally fill the screen on the server, the client will render the same items (avoiding a hash mismatch), and then the list will get updated dynamically from that point on. I'm happy to work on a PR if you're interested.
Hi! I love your project, its awesome!!!
I think I've run into a bug, or I'm doing something incorrectly because I can't get forceUpdateGrid to run the rowHeight function.
I have a list of components that can be expanded to see more info at which point i try to call the forceUpdateGrid function but it doesn't have an effect.
import React from 'react'
import { VirtualScroll,AutoSizer } from 'react-virtualized';
import DealroomBuilding from '../../containers/broker_dashboard/DealroomBuilding';
const DealroomStateList = React.createClass({
getInitialState(){
return {
buildings_expanded: {},
buildings_hiding_listings: {},
row_count: this.props.building_ids.length,
}
},
_onBuildingExpandToggle(b_id, is_expanded){
var self = this;
var buildings_expanded = this.state.buildings_expanded;
buildings_expanded[b_id] = is_expanded;
this.setState({buildings_expanded},
()=>{
self.refs.auto_sizer.refs.scroller.forceUpdateGrid();
}
);
},
_onShowListingsToggle(b_id, is_showing){
var self = this;
var buildings_hiding_listings = this.state.buildings_hiding_listings;
buildings_hiding_listings[b_id] = !is_showing;
//hack because i can't get virtual scroller to forceupdate (the index check part)
// so i have to update one of the properties of the virtualscroller
var row_count = this.state.row_count+1;
this.setState({buildings_hiding_listings, row_count},
()=>{
self.setState({
row_count: row_count-1,
})
}
);
},
_getVirtualScrollRow({index, isScrolling}){
if(index === 0){
return this._getDLCounterHtml();
}
return this._getDealroomBuildingHtml(index-1);
},
_getDLCounterHtml(){
return(
<div>
<div className='content-title' style={{'display': 'inline-block'}}>
{this.props.dl_count} {this.props.title}
</div>
<div style={{'display': 'inline-block'}}>
{this.props.children?
<span >
{this.props.children}
</span>
:
null
}
</div>
</div>
)
},
_getDealroomBuildingHtml(index){
const building_ids = this.props.building_ids;
const b_id = building_ids[index];
return(
<DealroomBuilding key={b_id} id={b_id}
onBuildingExpandToggle={this._onBuildingExpandToggle}
onShowListingsToggle={this._onShowListingsToggle}
/>
)
},
_getRowHeight({index}){
if(index === 0 || index > this.props.building_ids.length){
return 50;
}
const{
buildings_expanded,
buildings_hiding_listings,
} = this.state;
const b_id = this.props.building_ids[index - 1];
var height = 39;
if(buildings_expanded[b_id]){
height += 193;
}
else{
height += 59;
}
if(!buildings_hiding_listings[b_id]){
return height + 100;
}
return height
},
render(){
return(
<div className='content'>
<AutoSizer ref='auto_sizer'>
{({ height, width }) =>{ return(
<VirtualScroll
ref='scroller'
rowCount={this.state.row_count + 1}
rowHeight={this._getRowHeight}
rowRenderer={this._getVirtualScrollRow}
height={height}
width={width}
/>
)}}
</AutoSizer>
</div>
)
}
});
export default DealroomStateList;
the hack I've used to get around this is to have rowCount as a state variable which i increment then decrement to force the virtualscroller to have to rerender since its props change.
The hack is being used in _onShowListingsToggle. When that function is called everything works perfectly and the list is resized appropriately.
However when _onBuildingExpandToggle is called I call forceGridUpdate and nothing happens. I put a break point inside _getRowHeight, but its never called
Tested with IE10 and 11. The issue is this line:
var viewTop = typeof container.scrollY !== 'undefined' ? container.scrollY : container.scrollTop;
If container
is window
, scrollY
and scrollTop
are undefined in IE, so container.pageYOffset
must be used instead.
I'm testing a fix now and will PR.
Unmounting a component that uses react-virtual-list may cause it to produce the following warning:
Warning: setState(...): Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op. Please check the code for the vlist component.
If I disable throttleWithRAF
, the warning is gone, because there is no longer any asynchronicity. The vlist component should not call setState if it is no longer mounted.
getDOMNode
has been removed in v15, https://facebook.github.io/react/blog/2016/04/07/react-v15.html.
It is used in several places in code, e.g.
react-virtual-list/src/VirtualList.jsx
Line 78 in f7c96fe
Even the demo (if fresh compiled) does not work. After fixing some obvious bugs i gave up and used the version from August 22
(010197b) it is the one used in the online-demo I think.
thanks for your work anyways
Hey,
Thank you for the plugin.
I am trying to create something like this example: https://shakedos.com/examples/list/pwa.php. I was wondering if it would be possible to set the containerHeight to 100% so that it will automatically fit the size that is required.
Not sure if it's interesting, but that's the reason I am trying to do that: https://stackoverflow.com/questions/45824080/memory-issue-with-long-lists-in-a-web-app
Thank you again,
Shaked
Probably has something to do with how the scroll event works on mobile browsers. Originally reported by /u/sudorey
This looks like a handy component to use, but I'm very hesitant to actually utilize it since without an explicit license this source code defaults to "All Rights Reserved".
Scroll event does fire in the cordova only on the scroll process stopped.
Here is the article about this stuff https://developer.telerik.com/featured/scroll-event-change-ios-8-big-deal/
Does it possible to add the support for cordova using some other stuff/options? (maybe not to use the scroll event for cordova, maybe even setInterval instead - just to make it working after all)
I have a more 1000 items . But when I rendered use VirtualList not show all of item I have
this my screenshot : http://pasteboard.co/4aGIaY5Dy.jpg
`render(){
const MyList = ({
virtual,
itemHeight,
}) => (
<ul style={virtual.style}>
{virtual.items.map(item => (
<li key={`item_${item.id}`} style={{height: itemHeight}}>
Lorem ipsum dolor sit amet
</li>
))}
</ul>
);
const MyVirtualList = VirtualList()(MyList);
return (
<div >
<MyVirtualList
items={this.state.sourceList}
itemHeight={10}
/>
</div>
)
}`
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.