加载远程映像失败后加载本地映像

时间:2016-05-17 04:36:47

标签: react-native

如果远程图像失败,是否可以加载本地图像?

例如,我有以下代码:

<Image style={ styles.userImage }
       source={ { uri: http://example.com/my_image.jpg } }
       onError={(error) => ...}
/>

例如,如果我无权访问http://example.com/my_image.jpg,我将在onError中收到错误消息。有没有办法加载本地图像呢?

4 个答案:

答案 0 :(得分:15)

使用组件'状态。在构造函数中设置初始URL:

 this.state = { image: { uri: 'http://example.com/my_image.jpg' } }

创建onError处理程序:

 onError(error){
   this.setState({ image: require('your_local_image.path')})
 }

然后将它们组合在一起:

 <Image style={ styles.userImage }
       source={ this.state.image }
       onError={ this.onError.bind(this) }
 />

答案 1 :(得分:6)

根据最新文档,您可以使用defaultSource属性。它显示图像,直到原始图像加载,如果加载失败,则显示默认图像Link to docs

答案 2 :(得分:1)

要详细说明切尔诺夫的答案,您可以创建一个<Images />组件,为您将其抽象化:

import React from 'react';
import { Image } from 'react-native';

export default class Images extends React.Component {
  static defaultProps = {
    source: [],
    onError: () => {},
  }

  state = { current: 0 }

  onError = error => {
    this.props.onError(error);
    const next = this.state.current + 1;
    if (next < this.props.source.length) {
      this.setState({ current: next });
    }
  }

  render() {
    const { onError, source, ...rest } = this.props;
    return (
      <Image
        source={source[this.state.current]}
        onError={this.onError}
        {...rest}
      />
    );
  }
}

然后您可以像这样使用它:

import Images from './Images';

<Images
  source={[
    { uri: 'http://example.com/bad_image.jpg' },
    { uri: 'http://example.com/good_image.jpg' },
    require('./default.jpg'),
  ]}
  style={{
    backgroundColor: '#ccc',
    height: 200,
    width: 200,
  }}
/>

答案 3 :(得分:0)

像这样创建一个组件ImageLoad:

import React, {PureComponent} from 'react';
import PropTypes from 'prop-types';
import { Image, ImageBackground, ActivityIndicator, View } from 'react-native';

class ImageLoad extends PureComponent {
  static propTypes = {
    isShowActivity: PropTypes.bool,
  };

  static defaultProps = {
    isShowActivity: true,
    };

  constructor(props) {
    super(props);
    this.state = {
      isLoaded: false,
      isError: false
    };
  }

  onLoadEnd(){
    this.setState({
      isLoaded: true
    });
  }

  onError(){
    this.setState({
      isError: true
    });
  }

  render() {
    const {
      style, source, resizeMode, borderRadius, backgroundColor, children,
      loadingStyle, placeholderSource, placeholderStyle,
      customImagePlaceholderDefaultStyle
    } = this.props;
    return(
      <ImageBackground
        onLoadEnd={this.onLoadEnd.bind(this)}
        onError={this.onError.bind(this)}
        style={[styles.backgroundImage, style]}
        source={source}
        resizeMode={resizeMode}
        borderRadius={borderRadius}
      >
        {
          (this.state.isLoaded && !this.state.isError) ? children :
          <View
            style={[styles.viewImageStyles, { borderRadius: borderRadius }, backgroundColor ? { backgroundColor: backgroundColor } : {}]}
          >
            {
              (this.props.isShowActivity && !this.state.isError) &&
              <ActivityIndicator
                style={styles.activityIndicator}
                size={loadingStyle ? loadingStyle.size : 'small'}
                color={loadingStyle ? loadingStyle.color : 'gray'}
              />
            }
            <Image
              style={placeholderStyle ? placeholderStyle : [styles.imagePlaceholderStyles, customImagePlaceholderDefaultStyle]}
              source={placeholderSource ? placeholderSource : require('./Images/empty-image.png')}
            >
            </Image>
          </View>
        }
        {
          this.props.children &&
          <View style={styles.viewChildrenStyles}>
          {
            this.props.children
          }
          </View>
        }
      </ImageBackground>
    );
  }
}

const styles = {
  backgroundImage: {
    position: 'relative',
  },
  activityIndicator: {
    position: 'absolute',
    margin: 'auto',
    zIndex: 9,
  },
  viewImageStyles: {
    flex: 1,
    backgroundColor: '#e9eef1',
    justifyContent: 'center',
    alignItems: 'center'
  },
  imagePlaceholderStyles: {
    width: 100,
    height: 100,
    resizeMode: 'contain',
    justifyContent: 'center',
    alignItems: 'center'
  },
  viewChildrenStyles: {
    top: 0,
    left: 0,
    right: 0,
    bottom: 0,
    position: 'absolute',
    backgroundColor: 'transparent'
  }
}

export default ImageLoad;

并在您的应用中的任何地方使用它:

<ImageLoad
    style={{ width: 320, height: 250 }}
    loadingStyle={{ size: 'large', color: 'blue' }}
    source={{ uri: 'url image' }}
/>