React Native как заменить URL-адрес изображения при ошибке?

#react-native #react-native-android #react-native-image

#react-native #react-native-android #react-native-image

Вопрос:

У меня есть приложение, которое отображает несколько изображений, которые я загружаю из API. Теперь проблема в том, что срок действия некоторых изображений истек, что вызывает проблему на Android, в Android экран начинает отставать, как только на экране загружается изображение с истекшим сроком действия.

Я попытался заменить источник изображения onError={() => this.imgRefs[img_unique_id].setNativeProps({src: [{uri: this.state.workingUri}]})} этим методом, но он не работает. Я не могу использовать локальное состояние, поскольку оно не сохраняет выходные данные в локальном состоянии.

Я попробовал следующий код

   <Image  
      source={image.url} 
      progressiveRenderingEnabled={true}
      ref={item.id} 
      onError={(e) => this.refs[item.id].setNativeProps({source: [{uri: "working image URL"}]})} 
      resizeMethod={"scale"}>
   </Image>      
 

Приведенный выше код выдает мне неопределенную ошибку setNativeProps, и если я не использую onError на Android, это показывает мне ошибку утечки памяти.

Комментарии:

1. Почему вы не можете использовать локальное состояние в этом случае?

2.просто используйте native-base вместо необработанных конструкций react-native, native-base Image поддерживает неудачные изображения, предоставляя вам поддержку fallbackSource или даже fallbackComponent

Ответ №1:

Вот полный пример этого. Чтобы иметь собственное состояние для каждого FlatList элемента, я создал класс.

 import React, { Component, PureComponent } from 'react';
import { FlatList, Text, View, Image } from 'react-native';

class ItemClass extends PureComponent {
  state = {
    isImageExit: null
  }
  componentWillMount = () => {
    const { task } = this.props;
    Image.getSize(task.url, (width, height) => {
        if(width>0){
            this.setState({ isImageExit: true });
        }
        else{
            this.setState({ isImageExit: false });
        }
    }, () => {
      this.setState({ isImageExit: false });
    });
  }

  render() {
    const { isImageExit } = this.state;
    const { task } = this.props;
    const url = isImageExit ? task.url : 'https://dummyimage.com/600x400/000/fff';
    if (isImageExit === null) {
      return null;
    }
    return (
      <Image
        style={{ height: 200, width: 200 }}
        source={{ uri: url }}
      />
    );
  }
}

export default class App extends Component {
  render() {
    const data = [
      { url: 'url' },
      { url:'https://cdn.pixabay.com/photo/2017/08/05/18/53/mountain-2585069_1280.jpg' },
    ];
    return (
      <View style={{alignItems: 'center', top: 50}}>
          <FlatList
            data={data}
            renderItem={({ item }) => <ItemClass task={item} />}
          />
      </View>
    );
  }
}
 

Комментарии:

1. ваш код работал отлично, но проблема остается той же, как только изображение ошибки появляется в представлении, приложение становится медленным.

2. Вместо того, чтобы ждать, пока изображение перейдет в состояние ошибки, как я могу использовать getSize для предварительной загрузки изображения?

3. Обновлено, может быть, так лучше? Сначала image.getSize попытается загрузить и получить размер изображения. Пока это работает, ничего не отображается, или вы можете отобразить загрузочный компонент или то, что хотите. Когда getSize будет завершен, изображение тоже будет отображаться.

4. Я внедрил изменение, оно все еще медленное, и я думаю, что изображения замедляют работу FlatList после дополнительной загрузки. Я пробовал без изображений, все работает нормально.

Ответ №2:

Я думаю, вам следует использовать данные, полученные из Api, и соответствующим образом установить состояние внутри componentWillReceiveProps , потому что я думаю, что настройка состояния — лучший способ достичь этого результата. .

  this.setState = { image: { uri: 'image_uri_from_api' } }
 

Внутри <Image> добавить —

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

Внутри onError добавьте это —

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

Надеюсь, теперь это работает!

Комментарии:

1. Это react native, а не react web

2. спасибо, что дали мне знать. Я соответствующим образом обновил ответ.

3. Динамически загружается несколько изображений, как мне справиться с этой ситуацией?

4. да, я использую flatlist. На iOS это обрабатывается на стороне ОС, на Android это создает утечку памяти.

5. Есть ли способ, которым я могу передать функцию в исходном коде, которая сначала извлекает изображение, и в зависимости от размера я могу вернуть изображение или your_local_image ?.