Hi! Great project :)
My components are quite heavy and when I startup my app there are like 1.5 seconds where RLV hasn鈥檛 rendered yet and it appears blank, then suddenly pops in. Is there any way to know when RLV has rendered?
Something like an onLayout prop?
I thought scrollViewProps might help but it didn鈥檛 work.
If I can know when it rendered, I could implement some animations to make the RLV fade in smoothly.
Thanks!
Agreed. I could use ItemAnimator to figure out when a row has been rendered but not the whole list.
That would be really nice to have!
@wmonecke - The componentDidMount of the parent component (which renders the RecyclerListView) could be used to write the logic as it is called after the rendering of the RLV is completed.
Is it possible to re-open this issue? I really think it should be part of the RecyclerListView implementation as it is quite easy to have the list show nothing for up to 1 second while loading the content to render, even after the rest of the screen has rendered.
@josephmbeveridge Could you explain what you mean by showing nothing? Why would you want a one second delay even after the screen has rendered?
Sorry to clarify, it is common that the RecyclerListView will have mounted and as far as we know in React rendered, but it takes up to 1s before any content is actually displayed in the list. This means we don't know when it is actually finished rendering and when we should stop showing a spinner. Instead we have to hide the spinner immediately and the user sees nothing for a while.
So, You mean to say that the component has mounted but has not finished painting (appearing on the screen for the user to see) which would lead to the user seeing a white space. While such cases can occur rarely when the items are heavy, there is no way of knowing when the content has been painted onto the screen in react native. You could leave on the spinner for an extra second on top of recyclerlistview and hide it afterwards.
As a work around for react native, I use InteractionManager.runAfterInteractions inside the parent component's componentDidMount:
componentDidMount(): void {
// ...
InteractionManager.runAfterInteractions(() => {
// RecyclerListView has finished it's initial render
});
}
Downside to this is that this will wait for more than just the list to render, it waits for everything to render so you have to be careful with it's usage and what else is going on while the list is trying to render.
@aklinker1 I don't understand your workaround, would you be able to give an example, because in my app I have the same issue where it doesn't show anything for a 1-few seconds before showing the final list.
@callaars Here are some more fleshed out examples. If those don't help, what are you trying to accomplish after the list loads?
componentDidMount(): void {
InteractionManager.runAfterInteractions(() => {
runFunctionAfterListLoaded()
});
}
I have not ran this code, but I think it gets the idea across.
export default class ExampleList extends Component {
// Keep track of whether the list is "loaded"
public state = {
isLoaded: false,
};
public componentDidMount(): void {
InteractionManager.runAfterInteractions(() => {
// Consider it loaded once interactions are done - https://reactnative.dev/docs/interactionmanager
this.setState({ isLoaded: true });
});
}
public render(): JSX.Element {
return (
<RecyclerListView
...
// Include this prop so that when state.isLoaded changes, the list items get re-rendered
extendedState={state.isLoaded}
...
/>
);
}
}
Ah okay, sorry now I know what you mean. What I'm experiencing is that the RLV is rendered but showing a white screen before it renders whatever I got on my View. What you're doing is useful, but not so much in my case as the list is already ready at start. Thanks!
I used Item animator so I knew when my rows were mounted, then I called a callback to remove my placeholders in my parent component. Not the best way though because I'm calling callback multiple times which is useless.
@ingerable What do you mean by replacing the placeholders, changing the data provider?
@IoanaBdn I'm showing placeholders above (absolute position) my list until the list has been fully mounted. Though it's only for the mounting part. A render completion callback as asked in this ticket would be really nice.
<RecyclerListView
layoutProvider={this._layoutProvider}
dataProvider={this.state.dataProvider}
rowRenderer={this._rowRenderer}
itemAnimator={new ItemAnimator( () => { <------ using my itemAnimator
this.props.listHasMounted()
} )}
/>
class ItemAnimator extends BaseItemAnimator {
constructor(listHasMountedProp) {
super()
this.listHasMountedProp = listHasMountedProp;
}
animateDidMount(atX, atY, itemRef, itemIndex) {
//no need
this.listHasMountedProp();
}
}
Most helpful comment
Is it possible to re-open this issue? I really think it should be part of the RecyclerListView implementation as it is quite easy to have the list show nothing for up to 1 second while loading the content to render, even after the rest of the screen has rendered.