recyclerlistview
recyclerlistview copied to clipboard
Functional component on mobile doesn't update data properly
Ok, so this is kind of a niche bug, but I thought it is good sharing here
Here the functional component that encapsulates my recyclerList
const RecyclerList = ({itemRenderer,dataProvider,size}:RecyclerListProps) => {
const layoutProvider =new LayoutProvider(() => 0,() => {},)
return <RecyclerListView
layoutProvider={layoutProvider}
dataProvider={dataProvider}
forceNonDeterministicRendering={true}
canChangeSize={true}
rowRenderer={itemRenderer} />;
};
export default RecyclerList;
And here is how I render it in my main page
//THIS IS VERY IMPORTANT, FORGET PERFORMANCE IF THIS IS MESSED UP
const [dataProvider, setDataProvider] = useState(new DataProvider((r1, r2) => {
return r1 !== r2;
}).cloneWithRows(['don 1','don 2','don 3']))
return
{.......}
<RecyclerList
// @ts-ignore
dataProvider={dataProvider}
itemRenderer={(type:any,data:any)=>(
<View style={{width: Platform.OS==='web'?'100vw':'100%',}}>
<Item data={data} />
</View>
)}
/>
{......}
then, I have a button that when it's pressed it does this
setDataProvider(prev=>prev.cloneWithRows([...prev.getAllData(),'don 4']))
When the button is pressed, the first item renders ontop of the first one, like this

This only happens on mobile(on web it does not) and if it's a functional component, I have tested with a class component like below and it works fine without overlapping
export class RecycleTestComponent extends React.Component {
constructor(args:RecyclerListProps) {
super(args);
//@ts-ignore
this._layoutProvider = new LayoutProvider(() => 0,() => {},)
}
render() {
return <RecyclerListView
//@ts-ignore
layoutProvider={this._layoutProvider}
//@ts-ignore
dataProvider={this.props.dataProvider}
forceNonDeterministicRendering={true}
canChangeSize={true}
// @ts-ignore
rowRenderer={this.props.itemRenderer} />;
}
}
same here
I think LayoutProvider should be wrapped inside useRef.
Because otherwise it will be recreated every render
const layoutProvider = useRef(new LayoutProvider(() => 0,() => {})).current
I think LayoutProvider should be wrapped inside useRef. Because otherwise it will be recreated every render
const layoutProvider = useRef(new LayoutProvider(() => 0,() => {})).current
I have try it , and it works for me. Thanks very much !
I think LayoutProvider should be wrapped inside useRef. Because otherwise it will be recreated every render
const layoutProvider = useRef(new LayoutProvider(() => 0,() => {})).current
SUPER helpful... thank you!!!
This wasn't necessary with 3.x, but after upgrading to 4.x, we had a similar issue.