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.

[Android] Calling setNativeProps triggers Image load callbacks

See original GitHub issue

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: https://github.com/react-spring/react-spring/issues/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® Core™ 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: https://github.com/devhubapp/devhub/commit/682cc69b9c7252b73acb070e5cbcacc348f081e2

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>
  );
}
<div> </div>

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:19
  • Comments:10 (2 by maintainers)

github_iconTop GitHub Comments

3reactions
stale[bot]commented, Sep 20, 2020

Closing this issue after a prolonged period of inactivity. If this issue is still present in the latest release, please feel free to create a new issue with up-to-date information.

2reactions
cogellcommented, Jan 6, 2020

This stale bot is a tad aggressive…

Read more comments on GitHub >

github_iconTop Results From Across the Web

Bypassing Image Load Kernel Callbacks - MDSec
Whenever a system driver, executable image or dynamic linked library is loaded by the operating system, the registered image load routines are triggered....
Read more >
How to change the source of image by using setNativeProps ...
Coding example for the question How to change the source of image by using setNativeProps in react native-React Native.
Read more >
Detect scroll end in React Native ScrollView, snap to page
There are two different props you can set to React Native ScrollView which takes a callback to notify that scroll has ended.
Read more >
Animations - React Native
spring.addListener(callback) will invoke callback asynchronously while the animation is running, providing a recent value. This is useful for ...
Read more >
types/react-native/index.d.ts - UNPKG
320, setNativeProps(nativeProps: object): void;. 321. 322, /**. 323, * Requests focus for the given input or view. The exact behavior triggered.
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