Skip to content

[Android] Calling setNativeProps triggers Image load callbacks #25201

@brunolemos

Description

@brunolemos

When calling imageRef.setNativeProps(...) on Android, it triggers some callback methods, like onLoad, onLoadStart, etc. Only on Android and not on iOS/Web. It should not trigger these methods.

Explaining what this bug has caused

At the DevHub App, while the transparent images are loading, they have a discrete background color, like a placeholder. When they finish loading, I apply a #FFFFFF background. Because of this bug, when calling setNativeProps on onLoadEnd it would trigger another onLoadStart which would trigger another setNativeProps which would trigger another onLoadEnd and so on. This infinite loop was the cause of severe performance issues on Android, like this one: pmndrs/react-spring#570. I'm glad I finally found out the root cause!

I was able to detect this because I noticed the images on some android devices were blinking for apparently no reason (hint: there is always a reason)

React Native version: 0.59.8

Environment

React Native Environment Info:
System:
OS: macOS 10.14.5
CPU: (4) x64 Intel(R) Core(TM) i5-6267U CPU @ 2.90GHz
Memory: 17.80 MB / 16.00 GB
Shell: 3.2.57 - /bin/bash
Binaries:
Node: 11.5.0 - /usr/local/bin/node
Yarn: 1.15.2 - ~/.yarn/bin/yarn
npm: 6.9.0 - /usr/local/bin/npm
Watchman: 4.9.0 - /usr/local/bin/watchman
SDKs:
iOS SDK:
Platforms: iOS 12.2, macOS 10.14, tvOS 12.2, watchOS 5.2
Android SDK:
API Levels: 19, 22, 23, 24, 25, 27, 28
Build Tools: 23.0.1, 23.0.3, 24.0.3, 25.0.0, 25.0.1, 25.0.2, 25.0.3, 26.0.0, 26.0.1, 26.0.2, 26.0.3, 27.0.0, 27.0.1, 27.0.2, 27.0.3, 28.0.0, 28.0.2, 28.0.3
System Images: android-19 | Google APIs Intel x86 Atom, android-28 | Google APIs Intel x86 Atom, android-28 | Google Play Intel x86 Atom, android-Q | Google Play Intel x86 Atom
IDEs:
Android Studio: 3.4 AI-183.5429.30.34.5452501
Xcode: 10.2.1/10E1001 - /usr/bin/xcodebuild
npmGlobalPackages:
react-native-git-upgrade: 0.2.7
react-native-macos-cli: 2.0.1

Steps To Reproduce

  1. <Image ref={imageRef} onLoad={() => { console.log('onLoad'); }} />
  2. imageRef.current.setNativeProps({ style: { backgroundColor: 'red' } })
  3. Compare log between iOS and Android

Snack: https://snack.expo.io/@brunolemos/android-image-setnativeprops-onload

User-land workaround: devhubapp/devhub@682cc69

See code
import React, { useEffect, useRef, useState } from 'react';
import { Button, Image, ScrollView, Text, View } from 'react-native';

export default function App() {
  const imageRef = useRef(null);
  const [logs, setLogs] = useState([]);

  useEffect(() => {
    log('MOUNT');
  }, []);

  function log(text) {
    setLogs(l => [...l, text]);
  }

  function updateImageBg(color) {
    if (!(imageRef && imageRef.current)) return;

    imageRef.current.setNativeProps({
      style: { backgroundColor: color },
    });
  }

  return (
    <View style={{ flex: 1, paddingTop: 40, alignItems: 'center' }}>
      <Image
        ref={imageRef}
        onLoad={() => {
          log('onLoad');
        }}
        source={{
          uri:
            'https://cdn4.iconfinder.com/data/icons/logos-3/600/React.js_logo-512.png',
        }}
        style={{ width: 100, height: 100 }}
      />

      <View style={{ flexDirection: 'row' }}>
        <Button
          title="Green"
          onPress={() => updateImageBg('green')}
          style={{ flex: 1 }}
        />
        <Button
          title="Red"
          onPress={() => updateImageBg('red')}
          style={{ flex: 1 }}
        />
      </View>

      <ScrollView style={{ flex: 1 }}>
        {logs.map((log, index) => (
          <Text key={`log-${index}`}>{log}</Text>
        ))}
      </ScrollView>
    </View>
  );
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugComponent: ImagePlatform: AndroidAndroid applications.StaleThere has been a lack of activity on this issue and it may be closed soon.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions