question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Performance drop with FlatList + useDerivedValue

See original GitHub issue

Description

FlatList experiences a serious drop in performance when useDerivedValue is used inside the renderItem function (but only if we return shared value, if inside useDerivedValue return null everything is ok).

Screenshots

https://user-images.githubusercontent.com/47810008/107515749-7a9c0100-6bbc-11eb-885e-9043f642c1aa.mov

Steps To Reproduce

Run code below. Then change return value of useDerivedValue to null - after that everything should be smooth .

Expected behavior

Smooth 60 fps.

Actual behavior

If I scroll back and forth i can drop performance to ~ 3 fps.

Snack or minimal code example

import React from 'react'
import {StyleSheet, FlatList, View, Text} from 'react-native'
import Animated, {
  useAnimatedScrollHandler,
  useSharedValue,
  useDerivedValue
} from 'react-native-reanimated'

const AnimatedFlatList = Animated.createAnimatedComponent(FlatList)

const data = [...Array(300).keys()]

const Slider = () => {
  const transX = useSharedValue(0)
  
  const scrollHandler = useAnimatedScrollHandler({
    onScroll: (event) => {
      transX.value = event.contentOffset.x
    }
  })

  const renderItem = ({item, index}) => {
          return <Item index={index} item={item} transX={transX} />
        }

  return (
    <View style={styles.container}>
      <View style={styles.listContainer}>
        <AnimatedFlatList
          onScroll={scrollHandler}
          horizontal
          showsHorizontalScrollIndicator={false}
          style={styles.list}
          data={data}
          decelerationRate="fast"
          centerContent
          snapToInterval={15}
          scrollEventThrottle={16}
          snapToAlignment="center"
          renderItem={renderItem}
          keyExtractor={(item, index) => {String(index)}}
        />
      </View>
    </View>
  )
}

const Item = ({index, item, transX}) => {

    const udv = useDerivedValue(() => {
            return transX.value //change this to null
        })

    return (
        <Animated.View style={[styles.box]}>
            <Text style={styles.label}>{item}</Text>
        </Animated.View>
)}

const styles = StyleSheet.create({
    container: {
      flex: 1,
      alignItems: 'center',
      justifyContent: 'center'
    },
    listContainer: {
      height: 265,
      alignItems: 'center',
      justifyContent: 'center',
    },
    list: {
      height: 240,
      flexGrow: 0,
    },
    box: {
      width: 15,
      height: 150,
      backgroundColor: 'blue',
      borderRadius: 20,
      alignItems: 'center',
      justifyContent: 'center',
      borderColor:'black',
      borderWidth:1
    },
    label: {
      fontSize: 10,
      color: '#fff',
    },
  })

export default Slider

Package versions

  • React: 16.13.1
  • React Native: 0.63.4
  • React Native Reanimated: 2.0.0-rc.3
  • NodeJS: 14.15.5

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:3
  • Comments:9 (1 by maintainers)

github_iconTop GitHub Comments

5reactions
mxm87commented, Feb 10, 2021

The same thing happens with simple manual scroll, so that doesn’t related to FlatList by itself.

import React from 'react'
import {StyleSheet, FlatList, View, Text} from 'react-native'
import Animated, {
  useAnimatedGestureHandler,
  useSharedValue,
  useDerivedValue,
  useAnimatedStyle
} from 'react-native-reanimated'
import {PanGestureHandler} from 'react-native-gesture-handler'

const data = [...Array(300).keys()]

const Slider = () => {
  const transX = useSharedValue(0)

  const onGestureEvent = useAnimatedGestureHandler({
    onStart: (_, ctx) => {
        ctx.offsetX = transX.value
      },
    onActive: (event, ctx) => {
        transX.value = ctx.offsetX + event.translationX
      }
  })

  const animatedStyle = useAnimatedStyle(() => {
    return {
        flexDirection:'row',
        transform: [
            { translateX: transX.value }
        ]}
    })

  return (
      <View style={styles.container}>
          <PanGestureHandler onGestureEvent={onGestureEvent}>
            <Animated.View style={animatedStyle}>
                {data.map((item, index) => {
                    return <Item index={index} item={item} transX={transX} key={index}/>
                })}
            </Animated.View>
          </PanGestureHandler>
      </View>
  )
}

const Item = ({index, item, transX}) => {

    const udv = useDerivedValue(() => {
            return transX.value // <= change this to null
        })

    return (
        <View style={styles.box}>
            <Text style={styles.label}>{item}</Text>
        </View>
)}

const styles = StyleSheet.create({
    container: {
      flex: 1,
      alignItems: 'center',
      justifyContent: 'center'
    },
    box: {
      width: 15,
      height: 150,
      backgroundColor: 'blue',
      borderRadius: 20,
      alignItems: 'center',
      justifyContent: 'center',
      borderColor:'black',
      borderWidth:1
    },
    label: {
      fontSize: 10,
      color: '#fff',
    },
  })

export default Slider
2reactions
ehsan6shacommented, Nov 10, 2021

I’m facing the same issue using useAnimatedStyle both ScrollView and FlatList, any workarounds?

I couldn’t find any so I reverted to Animated library

Read more comments on GitHub >

github_iconTop Results From Across the Web

Optimizing Flatlist Configuration - React Native
Pros: This reduces time spent on the main thread, and thus reduces the risk of dropped frames, by excluding views outside of the...
Read more >
How to Make Performant Animations in React Native using ...
Reanimated enables us to create performant animations and user interactions that run quickly on the UI thread without any frame drops.
Read more >
Create high-performance graphics with React Native Skia
Thanks to the dev team behind react-native-skia, we can now use Skia in React Native applications to draw graphics and create UI concepts....
Read more >
useDerivedValue | React Native Reanimated
This hook allows for creating shared value reference that can change in response to updating of one or more other shared values.
Read more >
scrolleventthrottle flatlist - You.com | The search engine you control.
FlatList experiences a serious drop in performance when useDerivedValue is used inside the renderItem function (but only if we return shared value, ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found