Just migrated from 1.1.7 to 2.0.10, and now (mostly triggered by scrolling in my experience so far) I'm getting this warning:
Warning: Please report: Excessive number of pending callbacks: 501. Some pending callbacks that might have leaked by never being called from native code: {
"66781":{"module":"ReanimatedModule","method":"getValue"},
"66784":{"module":"ReanimatedModule","method":"getValue"},
"66787":{"module":"ReanimatedModule","method":"getValue"},
"66791":{"module":"ReanimatedModule","method":"getValue"},
"66794":{"module":"ReanimatedModule","method":"getValue"},
"66797":{"module":"ReanimatedModule","method":"getValue"},
"66800":{"module":"ReanimatedModule","method":"getValue"}, ...
I'm using
"react-native": "0.61.4",
"react-native-reanimated": "~1.4.0",
"react-native-gesture-handler": "~1.5.0",
with expo sdk 36
This is my list setup:
<DraggableFlatlist
onRef={ref => (this.tasksList = ref)}
style={{ flex: 1 }}
data={tasks}
initialNumToRender={10}
keyExtractor={task => `${task.id}`}
renderItem={this.renderItem}
extraData={this.props}
keyboardShouldPersistTaps="handled"
onRefresh={this.onRefresh}
refreshing={refreshing}
ItemSeparatorComponent={() => <ItemSeparator projectView={projectView} />}
onEndReached={this.fetchNextPage}
onEndReachedThreshold={0.5}
ListFooterComponent={this.renderFooter}
/>
...
renderItem = ({ item, index, drag, isActive }) => {
const props = {
key: item.id,
task: item,
onLongPress: drag,
index,
...otherPropsOmittedForClarity
}
return (
<View
style={isActive ? styles.draggingRow : {}}
pointerEvents={isActive ? 'none' : 'auto'}
>
<TaskRow {...props} />
</View>
)
}
Not sure if it's related, but I am also getting a bunch of ## can't measure (key) reason: no ref for tasks after the initial 10 (I log the key if we're trying to measure), and if I remove initialNumToRender I get in between 20-25 before the "can't measure" shows up.
The list items are variably sized tasks, where TaskRow is a
Happy to provide more details as needed, I'm a huge reanimated fan so I'm very excited to see this library be written with it. Thanks for all your hard work!
Thanks for the writeup, if you can provide a repro snack that would be awesome.
There was also an animation bug when row items were not all the same size -- I just released 2.0.11 which should fix it. However, the bug was related to calculating which row is currently hovered-over and doesn't sound related to what you describe above.
Also, I recently released a swipeable item component that may be useful to you: https://github.com/computerjazz/react-native-swipeable-item/blob/master/README.md
@computerjazz hoping to get you a snack repro by tuesday, otherwise it'll be at some point next week. I'll check out your swipeable item library, thanks!
@computerjazz found this issue so I'm trying to factor that into my debugging to see if it's the cause, it seems it is. Thoughts?
Yeah I'm aware of that issue, but I've verified in my own projects that it was fixed in RN 0.61.2, so it doesn't seem like it should apply here.
@computerjazz I'm starting to narrow down the cases in which it happens, using fast refresh and saving with the list items on screen is definitely one of them.
~However, there are instances where the renderItem function I pass to the list is called with index undefined - my render item method depends on the index for some logic and I think that might have an effect, any idea why that would happen?~
Just kidding, I dove into the library and read the componentDidUpdate logic. Obviously the nature of CDU isn't synchronous with render, is there something that can be done to ensure index isn't null when it's rendered? Only because it seems the items aren't guaranteed to re-render once the key is set
Oh yeah i've stopped using fast refresh after hitting a few other subtle bugs, which is too bad.
The only reason I can think of that an item wouldn't be called with an index is if it didn't exist in the keyToIndex map, which could be related to the ref issue above. Off the top of my head I'm not sure why that would be happening.
Yeah I had to include lots of performance optimization to make sure list items didn't rerender excessively. I'm sure there's room for improvement in getting items to rerender when we want them to.
I have two proposed solutions:
renderItem = () => {
...
if (!this.keyToIndex.get(itemKey)) this.keyToIndex.set(itemKey)
return (
...
)
}
but I don't like doing things with side effects in render
Going to try to the first solution and let you know if I get any weird behavior
@computerjazz not sure why I made it way more complicated than it had to be with the above solutions, I passed an "listIndex" where the index passed to the item is keyToIndex.get(itemKey) || listIndex
been using it in production and haven't had any issues with the pending callbacks
@dereknelson hey I'm running into the same issue. Would you mind explaining your solutions and how to implement? Thanks!
@eric-om when you call the renderItem in props just do something like
{ ...props, index: keyToIndex.get(itemKey) || listIndex }
@dereknelson sorry for the newb question but it's not clear to me where I should be using { ...props, index: keyToIndex.get(itemKey) || listIndex }
I'm passing a renderItem function to the renderItem prop on the DraggableFlatList.
The function: const renderItem = ({ item, index, drag, isActive }) => { ... }
I tried doing this in the renderItem prop renderItem={(props) => renderItem({ ...props, index: keyToIndex.get(itemKey) || listIndex })} but I got error Can't find variable: keyToIndex.
@eric-om when you call the renderItem in props just do something like
{ ...props, index: keyToIndex.get(itemKey) || listIndex }
Hi @dereknelson, could you maybe explain this with a little more context? I am currently running into similar issues and I am not able to completely follow your solution steps - would it be possible to see the entire file / code base - or is it a private app? Anyways - I would really appreciate your help!
Thanks!
Most helpful comment
@computerjazz not sure why I made it way more complicated than it had to be with the above solutions, I passed an "listIndex" where the index passed to the item is
keyToIndex.get(itemKey) || listIndex