问题
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;
回答1:
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"?
回答2:
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.
来源:https://stackoverflow.com/questions/50188373/onloadend-not-firing-in-react-native