Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flatlist Image source in React Native

I am trying to render a FlatList in React Native that it will be like an image carousel.

I want to provide the image sources in the assets folder and pass each items source in the renderItem but i get error undefined is not an object.

Here is the state:

export default function App() {
  const [images, setimages] = useState([
    {src:require('./assets/image1.png'),key:'1'},
    {src:require('./assets/image2.png'),key:'2'},
    {src:require('./assets/image3.png'),key:'3'},
    {src:require('./assets/image4.png'),key:'4'},
    {src:require('./assets/image5.png'),key:'5'}
  ]);

And here is the FlatList:

<FlatList
  horizontal={true} 
  showsHorizontalScrollIndicator={false} 
  data={images}
  renderItem={ ({images}) => (
    <Image source={images.src} style={{
      width:260,
      height:300,
      borderWidth:2,
      borderColor:'#d35647',
      resizeMode:'contain',
      margin:8
    }}></Image>
  )}
/>
like image 467
Panagiotis Iliakopoulos Avatar asked Dec 22 '22 18:12

Panagiotis Iliakopoulos


2 Answers

React Native FlatList renderItem callback get an object parameter with 3 props, item, index and separators:

renderItem

renderItem({item, index, separators});

You don't have to define keys in your array, just the images sources and then use item and index inside your renderItem function:

Define just an array with the sources:

const [images, setimages] = useState([
  require('./assets/image1.png'),
  require('./assets/image2.png'),
  require('./assets/image3.png'),
  require('./assets/image4.png'),
  require('./assets/image5.png')
]);

And use item and index for source and key:

return (
  <FlatList
    horizontal={true} 
    showsHorizontalScrollIndicator={false} 
    data={images}
    renderItem={ ({ item, index }) => (
      <Image source={item} /* Use item to set the image source */
        key={index} /* Important to set a key for list items,
                       but it's wrong to use indexes as keys, see below */
        style={{
          width:260,
          height:300,
          borderWidth:2,
          borderColor:'#d35647',
          resizeMode:'contain',
          margin:8
        }}
      />
    )}
  />
);

UPDATE

We should never use indexes for JSX keys because on a rearrangement or the array, we'll end up with the same indexes pointing to different items.

There is an ESLint rule regarding that issue eslint-plugin-react:

eslint-plugin-react

Prevent usage of Array index in keys (react/no-array-index-key)

Warn if an element uses an Array index in its key.

The key is used by React to identify which items have changed, are added, or are removed and should be stable.

It's a bad idea to use the array index since it doesn't uniquely identify your elements. In cases where the array is sorted or an element is added to the beginning of the array, the index will be changed even though the element representing that index may be the same. This results in unnecessary renders.

We should create unique keys for each item (and maybe store them inside our images array if we have a large items count) by using some fast hashing algorithms like CRC32 on the image name or by using nanoid to generate a random key for each image.

like image 133
Christos Lytras Avatar answered Feb 24 '23 17:02

Christos Lytras


This is happening because you're trying to destructure a images parameter which doesn't exist, it's called item.

Try this instead:

return (
    <FlatList 
        horizontal
        showsHorizontalScrollIndicator={false}
        data={images}
        renderItem={({ item }) => (
            <Image 
                source={item.src}
                style={{
                    width:260,
                    height:300,
                    borderWidth:2,
                    borderColor:'#d35647',
                    resizeMode:'contain',
                    margin:8
                }}
            />
        )}
    />
);
like image 32
emeraldsanto Avatar answered Feb 24 '23 17:02

emeraldsanto