react-infinite
react-infinite copied to clipboard
Infinite not working ok when resizing having dynamic heights
First of all I must say ReactInfinite is great. It's simple and solves a complex problem.
I am having an issue when trying to render a list with dynamic heights. I use ReactMeasure to get the proper height.
I noticed that if I resize the window, the elements from the screen dissapear prematurely. I am not sure if I am using the library wrongly or if I should change some of the state/props given to the component when resizing occurs.
const PostList = React.createClass({
mixins: [React.addons.PureRenderMixin],
getInitialState(){
return {
elementHeights: {}
}
},
loadingSpinnerDelegate(){
return <LoadingSpinner/>
},
handleResize( postId, index, { bounds, entry }){
const height = bounds.height;
this.setState((prevState, props) => ({
elementHeights: {
...prevState.elementHeights,
[postId]: height
}
}));
},
getElementHeight(){
return _.map(this.props.posts, (post) => this.state.elementHeights[post.id] || 300)
},
render(){
const { posts, pollFeature, loading, fetchNext } = this.props;
if(posts.length === 0){
return null;
}
return (
<Infinite
loadingSpinnerDelegate={this.loadingSpinnerDelegate()}
useWindowAsScrollContainer
elementHeight={this.getElementHeight()}
infiniteLoadBeginEdgeOffset={300}
isInfiniteLoading={loading}
onInfiniteLoad={fetchNext}
preloadBatchSize={Infinite.containerHeightScaleFactor(2)}>
{_.map(posts, (post, index) =>
<Measure.default key={post.id}
onResize={this.handleResize.bind(null, post.id, index)}
bounds>
{({ measureRef, measure, contentRect }) => (
<div ref={measureRef}>
<RegularPost key={post.id}
pollFeature={pollFeature}
post={post}
standalone={false}/>
</div>
)}
</Measure.default>
)}
</Infinite>
)
}
});
PostList.propTypes = PostFeed.propTypes;
Hmm I haven't looked into this too much, but this might be because we don't recompute the size of the window when it is resized when using useWindowAsScrollContainer
, which we should certainly fix.
I haven't looked at the implementation yet but I was suspecting that. I will see if I can find the problem in the source code and submit a pull request.
Thanks @garetht
@garetht Do you know a quick workaround for this? It seems that the containerHeight is not kept as an internal state, so this might be a huge refactor if I am not wrong?
It might be possible to just modify computedProps
directly with a listener on window resize, although that is on the hacky side. this.props
is rarely used directly.
@garetht I have been working on the """hack""" and the resize sometimes work and sometimes doesn't. I wanted to ask you if you knew where this error could come from.
Basically I added a resize handler that does something similar to what is done in componentWillReceiveProps:
handleResize(e) {
var nextInternalState = this.recomputeInternalStateFromProps(this.props, window.innerHeight);
this.computedProps = nextInternalState.computedProps;
this.utils = nextInternalState.utils;
this.setState(nextInternalState.newState);
},
As you see, the recomputeInternalStateFromProps
now receives a height. Which is used and replaced in the generateComputedProps
method:
recomputeInternalStateFromProps(props: ReactInfiniteProps, forcedHeight = null): {
computedProps: ReactInfiniteComputedProps,
utils: ReactInfiniteUtilityFunctions,
newState: ReactInfiniteState
} {
checkProps(props);
var computedProps = this.generateComputedProps(props, forcedHeight);
...
generateComputedProps(props: ReactInfiniteProps, forcedHeight = null): ReactInfiniteComputedProps {
// These are extracted so their type definitions do not conflict.
var {containerHeight,
preloadBatchSize,
preloadAdditionalHeight,
...oldProps} = props;
var newProps = {};
containerHeight = typeof containerHeight === 'number' ? containerHeight : 0;
if (forcedHeight) {
newProps.containerHeight = forcedHeight;
} else {
newProps.containerHeight = props.useWindowAsScrollContainer
? window.innerHeight : containerHeight;
}
....
However, depending on the size of the screen elements might dissapear.
What else can I check specifically? I am trying to debug the code.
still working?