Closed neo773 closed 2 months ago
I've personally found that Flatlist is quite slow on macOS and haven't completely root caused it quite yet. I wonder if the issue is more Flatlist than the actual prop. You might want to try just putting a bunch of views in a ScrollView to compare, or using an alternative like Flashlist.
I've personally found that Flatlist is quite slow on macOS and haven't completely root caused it quite yet. I wonder if the issue is more Flatlist than the actual prop. You might want to try just putting a bunch of views in a ScrollView to compare, or using an alternative like Flashlist.
I've also found it slow but my current issue is with hover events it's just super slow in general. Rendering it in a normal list didn't make difference either. It's reproducible even with a single element try moving the cursor in and out quickly over it.
Side note, @neo773 are you a discord engineer? Or building a discord client using public APIs?
In a similar demo of a onHoverIn
and onHoverOut
(which you can find here), I'm not able to repro the error. I may have a faster machine as well, but it feels like there's something inherently different between the two videos more than just hardware. From the attached video, it feels more like a symptom of extraneous re-renders or re-rendering the whole View instead of just the item for every hover. Could you try making a blank or simple app and reproducing, and/or try using something like why-did-you-render to verify the only re-rendered element on hover is the Pressable?
https://github.com/microsoft/react-native-macos/assets/6722175/920df043-34f6-4aec-8b60-e76ddce727d3
So I looked at the test you referenced and it seems like it's rendering a native menu list I could not find any onHoverIn
or onHoverOut
use in the test code, I even went deeper into the component's code and didn't find any reference there either.
Anyways here's a minimal reproducible code
import { Text, FlatList } from 'react-native';
import React, { useState } from 'react';
import { Pressable, View } from 'react-native-macos';
const BugScreen = () => {
const [hoveredIndex, setHoveredIndex] = useState<number | null>(null);
const dummyData = Array.from({ length: 100 }, (_, index) => ({
id: `dm-${index}`,
user: {
username: `User ${index}`,
},
}));
const renderItem = ({
item: item,
index: index,
}: {
item: {
id: string;
user: {
username: string;
};
};
index: number;
}) => {
return (
<Pressable
style={{
flexDirection: 'row',
marginVertical: 2,
alignItems: 'center',
backgroundColor: index === hoveredIndex ? '#404249' : 'transparent',
// @ts-expect-error
cursor: 'pointer',
}}
onHoverIn={event => {
setHoveredIndex(index);
}}
onHoverOut={() => {
setHoveredIndex(null);
}}>
<Text style={{ color: 'black', marginLeft: 2, fontWeight: 'bold' }}>
{item.user.username}
</Text>
</Pressable>
);
};
return (
<FlatList
data={dummyData}
renderItem={renderItem}
keyExtractor={dm => dm.id}
contentContainerStyle={{ padding: 8 }}
showsVerticalScrollIndicator={false}
ListHeaderComponent={() => {
return (
<View style={{ marginLeft: 1, marginVertical: 2 }}>
<Text style={{ color: '#949BA4', fontSize: 12, fontWeight: '500' }}>
DIRECT MESSAGES
</Text>
</View>
);
}}
/>
);
};
export default BugScreen;
Side note, @neo773 are you a discord engineer? Or building a discord client using public APIs?
Nah, I'm building an open source client using private APIs
@neo773 not a native menu, a React Native drop in replacement for a menu, which each item being JS (I worked on it 🙂). 'useMenuItem' would be where where hover is used, but the code is convoluted, so don't feel the need to look deeper.
I'll look at your example code when I can!
@neo773 not a native menu, a React Native drop in replacement for a menu, which each item being JS (I worked on it 🙂). 'useMenuItem' would be where where hover is used, but the code is convoluted, so don't feel the need to look deeper.
I'll look at your example code when I can!
I'll try running your example code when I can. However just from looking at it, the useState for the hook is top level, and will re-render the whole Flatlist every time. Try using "listItemComponent' instead of renderItem (not well documented, but it's basically renderItem with better support for hooks), and see if you can perhaps wrap the item in a call to React.useMemo() to prevent unnecessary renders?
It's a busy week for me, but I'll try running your code when I can too.
Tried the ListItemComponent
prop and memoizing the item, now it just skips lot of frames
It's a busy week for me, but I'll try running your code when I can too.
I get it, take your time and thanks for looking into it.
https://github.com/microsoft/react-native-macos/assets/62795688/16d48897-0a23-464e-887d-d9e21ec11fd8
Environment
Steps to reproduce the bug
Pressable
onHoverIn
onHoverOut
is too slow to be used in a list it has a huge latencyhttps://github.com/microsoft/react-native-macos/assets/62795688/29dbc19e-a42c-46f6-a60c-95e3b7fa3f68
My code
Expected Behavior
No response
Actual Behavior
No response
Reproducible Demo
No response
Additional context
No response