'onLoadEnd is not fired in react-native Image
hi am trying to load an remote image. onLoadStart is hitting but not the onLoadEnd `
<View style={{ paddingTop: 60, paddingBottom: 10 }}>
{this.state.loading ? (
<DotIndicator size={25} color={"white"} />
) : (
<Image
resizeMode={this.resizeMode}
style={[styles.imageStyle, this.tintStyle]}
onLoadStart={e => {
this.setState({ loading: true });
}}
onLoadEnd={e => this.setState({ loading: false })}
// defaultSource={NoProfile}
// loadingIndicatorSource={require("@images/profile_placeholder.png")}
source={this.userImageUri}
onError={error => {
this.tintStyle = { tintColor: "lightgray" };
this.resizeMode = "contain";
this.userImageUri = NoProfile;
}}
/>
)}
</View>
`
EDIT 1
onLoadStart is hit. onLoad is also never being called
does any one have a clue. am new to react. Any help is appreciated. thanks is advance
SOLUTION
Since Vignesh and hong mentioned the image is never there so its on loadEnd will never be called. So instead of loading only image or loader I loaded the loader on top of image. Posting this here as it may be useful for someone at sometime. Once again thanks to Vignesh and hong
<View
style={{
padding: 10,
width: WIDTH - 50,
height: WIDTH - 25,
alignSelf: "center"
}}
>
{this.state.loading ? (
<MaterialIndicator
size={50}
color={"red"}
style={{
marginTop: WIDTH / 2,
alignSelf: "center"
}}
/>
) : null}
<Image
resizeMode={this.resizeMode}
style={[styles.imageStyle, this.tintStyle]}
onLoadStart={e => {
this.setState({ loading: true });
}}
onLoad={e => {
this.setState({ loading: false });
}}
onLoadEnd={e => this.setState({ loading: false })}
// defaultSource={NoProfile}
// loadingIndicatorSource={require("@images/profile_placeholder.png")}
source={this.userImageUri}
onError={error => {
this.tintStyle = { tintColor: "lightgray" };
this.resizeMode = "contain";
this.userImageUri = NoProfile;
}}
/>
</View>
Solution 1:[1]
Let's say that the value of this.state.loading
was false
before the first render.
When the first render happens, this.state.loading ?
returns the Image
component, onLoadStart
is triggered and this.state.loading
is set to true
.
When the second render happens, this.state.loading
is found to be true
and this.state.loading ?
returns the DotIndicator
component. All the hard work done by the Image
component during the previous the render is lost. In fact, Image
component was never present in that context.
Hence, onLoadingEnd
will never be triggered, because Image
component never appeared in the second render.
And the DotIndicator
will forever go round and round and round... Waiting for it's lost love..
Solution 2:[2]
If loading
is true
from the beginning, nothing will be called in the image.
If loading
value is false
at first, the image does not see loadStart
running, only load
function and loadEnd
function will be called.
This is because the loadStart
function runs when the start value is false
and it is already rendered. And if the start value is true
, nothing is done because it does not draw an image.
This is a very simple example that you can experiment with:
import React, { Component } from 'react';
import { View, Image } from 'react-native';
export default class App extends Component {
state={
loading: false,
}
render() {
return (
<View>
{this.state.loading ? (
<Image
style={{width: 100, height: 100}}
source={{uri: 'https://facebook.github.io/react-native/img/tiny_logo.png'}}
/>
) : (
<Image
style={{width: 50, height: 51}}
onLoadStart={e => this.setState({ loading: true })}
onLoad={e => alert("onLoad")}
onLoadEnd={e => alert("onLoadEnd")}
source={require('@expo/snack-static/react-native-logo.png')}
/>)}
</View>
);
}
}
Solution 3:[3]
I ended up copying the same image but set its style to width: 1, height: 1. this will always be displayed but is not visible. What this allows is to continue to set the state despite the many rerenders. I then in a if statement have the actual image or a text component that will display image not found. By default NoImageFound is set to true. Here is my code
<Image
source={{ uri: image }}
style={{ width: 1, height: 1 }}
onLoadStart={() => setNoImageFound(true)}
onLoad={() => setNoImageFound(false)}
/>
{noImageFound ? (
<View style={{ justifyContent: "center", alignItems: "center" }}>
<Text style={{ textAlign: "center" }}>No image found</Text>
</View>
) : (
<View style={styles.icon}>
<Image source={{ uri: image }} style={styles.image} />
</View>
)}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Vignesh V Pai |
Solution 2 | hong developer |
Solution 3 | Freddie Banfield |