My images disappear

I am having the worst issue with disappearing images. The images will initially load, but after I navigate away from the component, they will disappear and not come back. All the images are in my app package and should be bundled with the app.

Using Expo 33 on a Fire Tablet. I have set my assetBundlePatterns to "**/*" and all the images are preloaded.

My root component:

import React from 'react'
import Navigator from '~/navigation'
import { AppLoading } from 'expo'
import Sentry from 'sentry-expo'
import { SENTRY_DSN } from 'react-native-dotenv'

import { loadAssetsAsync } from '~/utils/assets'

Sentry.config(SENTRY_DSN).install()

export default class AppRoot extends React.Component {
  state = {
    isReady: false,
  }

  _loadAssetsAsync() {
    const imageAssets = [
      // Slides
      require('~/assets/slides/1.jpg'),
      require('~/assets/slides/2.jpg'),
      require('~/assets/slides/3.jpg'),
      require('~/assets/slides/4.jpg'),

      // Products
      require('~/assets/products/category/1.jpg'),
      require('~/assets/products/category/2.jpg'),
      require('~/assets/products/category/3.jpg'),
      require('~/assets/products/category/4.jpg'),
    ]
    const fontAssets = {
      'brush-script': require('~/assets/fonts/brush-script.ttf'),
    }

    return loadAssetsAsync(imageAssets, fontAssets);
  }

  render() {
    if (!this.state.isReady) {
      return (
        <AppLoading
          startAsync={this._loadAssetsAsync}
          onFinish={() => this.setState({ isReady: true })}
          onError={console.warn}
        />
      )
    }

    return <Navigator />
  }
}

assets.js

import { Image } from 'react-native'
import * as Font from 'expo-font';
import { Asset } from 'expo-asset';

export const cacheFonts = fonts => Font.loadAsync(fonts)

export const cacheImages = images => (
  images.map(image => {
    if (typeof image === 'string') {
      return Image.prefetch(image)
    } else {
      return Asset.fromModule(image).downloadAsync()
    }
  })
)

export const loadAssetsAsync = (images, fonts) => {
  const imageAssets = cacheImages(images)
  const fontAssets = cacheFonts(fonts)
  return Promise.all([imageAssets, fontAssets])
}

Component with image (ProductItem.js):

import React from 'react'
import { StyleSheet, TouchableOpacity, Image, Text } from 'react-native'
import { Actions } from 'react-native-router-flux'

export default class ProductItem extends React.Component {
  render() {
    const { product } = this.props

    return (
      <TouchableOpacity
        style={styles.productItem}
        onPress={() => Actions.product({ product })}
      >
        <Image
          style={styles.productImage}
          source={product.image}
        />
        <Text style={styles.productTitle}>
          { product.name }
        </Text>
      </TouchableOpacity>
    )
  }
}

const styles = StyleSheet.create({
  productItem: {
    flex: 1,
    margin: 20,
    alignItems: 'center',
  },
  productImage: {
    flex: 1,
    width: 200,
    height: 200,
    resizeMode: "contain",
  },
  productTitle: {
    color: '#ffffff',
    fontSize: 20,
  },
})

Grid containing image component (ProductGrid.js)

import React from 'react'
import Grid from 'react-native-grid-component'
import ProductItem from '~/components/ProductItem'

export default class ProductGrid extends React.Component {
  renderProduct = (product, index) => (
    <ProductItem product={product} />
  )

  render() {
    const { products } = this.props

    return (
      <Grid
        data={products}
        numColumns={2}
        renderItem={this.renderProduct}
        keyExtractor={(item, index) => item.name}
      />
    )
  }
}

The products array:

[
  {
    name: '1',
    type: 'type1',
    blurb: 'Lorem ipsum...',
    image: require('~/assets/products/category/1.jpg')
  },
  {
    name: '2',
    type: 'type2',
    blurb: 'Lorem ipsum...',
    image: require('~/assets/products/category/2.jpg')
  },
  {
    name: '3',
    type: 'type3',
    blurb: 'Lorem ipsum...',
    image: require('~/assets/products/category/3.jpg')
  },

  ...
]

Could you add a code snippet showing how you use the ProductItem component?

Done!

Does anyone have any ideas as to how I can fix this?

Can you provide a more complete runnable reproducible example? Is there any way to reproduce outside of a Fire tablet?

I have some fire tablets here. If be builds a snack or a repo I can easily grab I can run some tests

Thank you so much for responding @notbrent @mackbrowne.prodigy. Please give me several days to bundle this up for you (on vacation for the holiday).

Thanks for the patience! I have published a project here that reproduces the issue: Expo

The issue only shows in a production build (expo build:android) on the device, not in the Expo app.

To reproduce:

  1. Press the white circle to see the product list
  2. Press the white circle again to go back
  3. Repeat about 10 (±5) times
  4. The images will not load

@joshua-s I don’t have access to your code thorugh the snack and won’t be able to build. Can you provide me with a github link and I’ll install and build it?

The code can be found at:

@mackbrowne.prodigy were you successfully able to access the code and build it?

I didn’t realize I needed to do a full standalone build for this. I’ll need a bit more time to test this out. I’d drop it into my existing build processes in circleCI, but im unsure of the implications of doing that to a project that’s already released to Production.

1 Like

This topic was automatically closed 15 days after the last reply. New replies are no longer allowed.