onLoadEnd not firing in react native
Asked Answered
C

2

6

I am trying to display GIF from the giphy api on react native. Gifs take time to display on screen so I want to display a spinner on the midtime. The onLoadEnd event seem to be never fired on the Image tag, so the spinner actually runs endlessly because I can never update loading in my state. What am I doing wrong here ?

import React, { Component } from 'react';
import { View, Text, ScrollView, Image} from 'react-native';
import axios from 'axios';
import QuoteDetail from './quote_detail'
import Spinner from './spinner'

// class based component knows when it's gona be rendered
class QuoteList extends Component {
  state = { quotes: [],
            giphyUrl: 'https://media.giphy.com/media/nZQIwSpCXFweQ/giphy.gif',
            loading: true
          };

  componentWillMount() {
    console.log('Again?')
    axios.get('https://api.tronalddump.io/search/quote?query='+this.props.characterName)
      .then(response => this.setState({ quotes: response.data._embedded.quotes }))
    this.getGiphy()
  }

  getGiphy() {
    console.log('getgif')
    const GiphyUrl = "https://api.giphy.com/v1/gifs/search?api_key=mBJvMPan15t7TeLs8qpyEZ7Glr5DUmgP&limit=1&q=" + this.props.characterName.replace(" ", "+");
    console.log(GiphyUrl)
    axios.get(GiphyUrl)
      .then(response => {
                  console.log(response)
                  console.log(response.data.data[0].url)

                  this.setState({ giphyUrl: response.data.data[0].images.original.url})
                  console.log(this.state)
                })

  }

  renderQuotes() {
    return this.state.quotes.map(
      quote => <QuoteDetail key={quote.quote_id} quote={quote}/>
    );
  }



  render() {
    if (this.state.loading) {
      return < Spinner />;
    }
    else {
      return (
        <ScrollView>
          <View style={styles.viewStyle}>
            <Image
              source={{uri: this.state.giphyUrl}}
              key={this.state.giphyUrl}
              style={styles.gifStyle}
              onLoadEnd={() => console.log('im done loading')}
            />
            <Text style={styles.vsStyle}>VS</Text>
            <Image
              source={{ uri: "https://media.giphy.com/media/xTiTnHXbRoaZ1B1Mo8/giphy.gif"}}
              key="https://media.giphy.com/media/xTiTnHXbRoaZ1B1Mo8/giphy.gif"
              style={styles.gifStyle}
            />
          </View>
          {this.renderQuotes()}
        </ScrollView>
      );
    }
  }
}

const styles = {
  gifStyle: {
    height: 200,
    width: 190
  },
  viewStyle: {
    flexDirection: 'row'
  },
  vsStyle: {
    marginTop: 95,
    marginLeft: 5,
    marginRight: 5,
    fontWeight: 'bold',
    fontSize: 20
  }
};

export 

default QuoteList;

Contrapuntist answered 5/5, 2018 at 10:23 Comment(0)
R
1

Your component mounts with the state property 'loading' set to true. In your render method, you're conditionally rendering either your spinner -or- your image-containing scrollview based on whether 'loading' is true, and I'm not seeing any place in your code example where 'loading' is ever set to false. This means that your <Image /> is never rendered, so it never loads in the first place, so the onLoadEnd will never be called.

I would still only conditionally render the spinner, but would approach it more like this:

render() {
  return (
    <View>
      <ScrollView>
        <View style={styles.viewStyle}>
          <Image
            source={{uri: this.state.giphyUrl}}
            key={this.state.giphyUrl}
            style={styles.gifStyle}
            onLoadEnd={() => this.setState({loading: false})}
          />
          <Text style={styles.vsStyle}>VS</Text>
          <Image
            source={{uri:"https://media.giphy.com/media/xTiTnHXbRoaZ1B1Mo8/giphy.gif"}}
        key="https://media.giphy.com/media/xTiTnHXbRoaZ1B1Mo8/giphy.gif"
            style={styles.gifStyle}
          />
        </View>
        {this.renderQuotes()}
      </ScrollView>
      {this.state.loading && <Spinner />}
    </View>
  );
}

Give your spinner an absolute position so that it renders over the scrollview.

Recipe answered 20/5, 2018 at 5:14 Comment(0)
F
0

One thing that seems wrong here is the getGiphy and renderQuotes properties that are not arrow functions or don't bind "this" in the constructor. Judging by your code, you can't use the setState function cause of the wrong "this" scope.

Try this to see if this works

getGiphy = () => {...}
renderQuotes = () => {...}

Are you sure you don't get an error like "setState is undefined"?

Flutist answered 13/5, 2018 at 17:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.