moti: Skeleton makes navigation transitions slow by 200-400ms

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

When I put a Skeleton loader inside a screen and navigate to it, the app hangs for 200ms-400ms while the loader renders when comparing this to rendering null, ActivityIndicator, or any other custom loading component.

Expected Behavior

Ideally, the Skeleton loader should not add any extra time to the loading sequence, which would give a bad UX to the user. However, using Reanimated may introduce some extra time but hopefully that can be sub-100ms so provide an acceptable UX.

Steps To Reproduce

No response

Versions

- Moti: 0.21.0
- Reanimated: 2.12.0
- React Native: 0.70.5
- Expo SDK v47

Screenshots

Without Skeletons:

 LOG  Sentry Logger [log]: [Measurements] Adding measurements to transaction {
  "stall_count": {
    "value": 0,
    "unit": "none"
  },
  "stall_total_time": {
    "value": 0,
    "unit": "millisecond"
  },
  "stall_longest_time": {
    "value": 0,
    "unit": "millisecond"
  }
}
 LOG  Sentry Logger [log]: [Tracing] Finishing navigation transaction: AllFriends.
 LOG  Sentry Logger [log]: [Measurements] Adding measurements to navigation transaction AllFriends: {
  "frames_total": {
    "value": 312,
    "unit": "none"
  },
  "frames_frozen": {
    "value": 0,
    "unit": "none"
  },
  "frames_slow": {
    "value": 2,
    "unit": "none"
  }

With Skeletons:

 LOG  Sentry Logger [log]: [Measurements] Adding measurements to transaction {
  "stall_count": {
    "value": 3,
    "unit": "none"
  },
  "stall_total_time": {
    "value": 348.51123046875,
    "unit": "millisecond"
  },
  "stall_longest_time": {
    "value": 159.5732421875,
    "unit": "millisecond"
  }
}
 LOG  Sentry Logger [log]: [Tracing] Finishing navigation transaction: AllFriends.
 LOG  Sentry Logger [log]: [Measurements] Adding measurements to navigation transaction AllFriends: {
  "frames_total": {
    "value": 1043,
    "unit": "none"
  },
  "frames_frozen": {
    "value": 0,
    "unit": "none"
  },
  "frames_slow": {
    "value": 6,
    "unit": "none"
  }
}

Reproduction

Here is the Skeleton code I am using:

const Loader = () => {
  
  const renderSkeletonItem = () => (
    <View
      style={{
        flexDirection: "row",
        justifyContent: "space-between",
        marginBottom: 10,
        alignItems: "center",
      }}
    >
      <View style={{ flexDirection: "row", alignItems: "center" }}>
        <Skeleton height={50} width={50} radius="round" />
        <View style={{ marginLeft: 8 }}>
          <Skeleton height={16} width={124} />
          <View style={{ height: 8 }} />
          <Skeleton height={16} width={100} />
        </View>
      </View>
      <Skeleton height={35} width={91} radius="round" />
    </View>
  );

  return (
    <Skeleton.Group show={true}>
      {[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map((index) => (
        <View key={index}>
          <View
            style={{
              flexDirection: "row",
              justifyContent: "space-between",
              marginBottom: 10,
              alignItems: "center",
            }}
          >
            <View style={{ flexDirection: "row", alignItems: "center" }}>
              <Skeleton height={50} width={50} radius="round" />
              <View style={{ marginLeft: 8 }}>
                <Skeleton height={16} width={124} />
                <View style={{ height: 8 }} />
                <Skeleton height={16} width={100} />
              </View>
            </View>
            <Skeleton height={35} width={91} radius="round" />
          </View>
        </View>
      ))}
    </Skeleton.Group>
  );

  return (
    <Skeleton.Group show={false}>
      <FlatList
        contentContainerStyle={{ marginHorizontal: 16 }}
        data={[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]}
        ListHeaderComponent={<Skeleton height={48} width="100%" />}
        ListHeaderComponentStyle={{ marginVertical: 16 }}
        renderItem={renderSkeletonItem}
      />
    </Skeleton.Group>
  );
};

As you can see, I have one version that renders it with a FlatList, another one that just uses .map(). So, the issue is with Skeleton.

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 18 (11 by maintainers)

Most upvoted comments

@nandorojo Sorry for the slow response. First off, I want to thank you for being so responsive and being such a great library maintainer alongside your job!

I tried that solution and it made 0 change to the performance metrics I shared.