I am learning. I’m doing a delivery layout.
I reached a part where I need to load Cards with the restaurants, the names are going correctly, but I can’t place the images.
I’m using a JSON file, with a ‘restaurants’ type, containing id, name, image.
File structure:
/
|--/src
|--/App
| |--index.tsx
|--/components
| |--/restaurants
| |--index.tsx
| |--/restaurantCard
| |--index.tsx
|--/assets
|--/restaurants
|--all images png
RestaurantCard Component:
import { View, Text, Pressable, Image } from 'react-native'
import { RestaurantsProps } from '..'
import { FontAwesome, Ionicons } from '@expo/vector-icons'
export default function RestaurantCard({ item }: { item: RestaurantsProps }) {
const width = 140;
const height = 100;
// This line works
const Logo = Image.resolveAssetSource(require(`@/src/assets/restaurants/kfc.png`)).uri
// This dont works
// const Logo = Image.resolveAssetSource(require(`@/src/assets/restaurants/${item.image}`)).uri
return (
<Pressable style={{
marginVertical: 4,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#c8c8c8',
borderRadius: 16,
}}
onPress={() => { console.log(`CLICOU EM ${item.name}`) }}
>
<View style={{
width: width,
height: height,
backgroundColor: 'black',
borderRadius: 16,
}}>
<Image source={{uri: Logo}} style={{
width: width,
height: height,
resizeMode: 'stretch',
borderRadius: 16,
}} />
</View>
<FontAwesome name='circle' size={38} color={'#aaa'} style={{
position: 'absolute',
bottom: 26,
}} />
<Ionicons name='fast-food-outline' size={24} style={{
position: 'absolute',
bottom: 32,
color: '#ddd'
}} />
<Text className='font-semibold text-gray-600 text-lg mt-5'>{item.name}</Text>
</Pressable>
)
}
Restaurant list component:
import { useEffect, useState } from 'react'
import { View, FlatList } from 'react-native'
import RestaurantCard from './restaurantCard';
import * as restaurantesJson from '@/db.json'
export interface RestaurantsProps {
id: string;
name: string;
image: string
}
export function Restaurants({ urlFetch }: { urlFetch: string }) {
const [restaurants, setRestaurants] = useState<RestaurantsProps[]>([])
useEffect(() => {
//This async function was an attempt, but nothing changed
async function getRestaurantsJson() {
// console.log(data);
setRestaurants(restaurantesJson.restaurants);
console.log(restaurants);
}
getRestaurantsJson()
}, []);
return (
<View>
<FlatList
horizontal={true}
data={restaurants}
renderItem={({ item }) => <RestaurantCard item={item} />}
showsHorizontalScrollIndicator={false}
contentContainerStyle={{
gap: 12,
justifyContent: 'center',
alignItems: "center"
}}
/>
</View>
)
}
I don’t know what I have to do
I need an solution that loads the images automatically, without needing me to create a file exporting them all.
we can solve these is different approach
Note: your RestaurantsProps image name and local assets image name should be same
Like:
load all images in to a local array like
const img = {
"kfc.png": require('@/src/assets/restaurants/kfc.png'),
"mcdonalds.png": require('@/src/assets/restaurants/mcdonalds.png'),
.....,
}
..
const logo = img[item.image]
<Image source={Logo}>
The issue you’re encountering arises from the fact that dynamic imports using require() in React Native do not work directly with variables.
To solve this, you can use a workaround by preloading the images into an object that maps image filenames to require statements. Here’s how you can do it:
const images: { [key: string]: any } = {
"kfc": require('@/src/assets/restaurants/kfc.png'),
"burgerking": require('@/src/assets/restaurants/burgerking.png'),
"mcdonalds": require('@/src/assets/restaurants/mcdonalds.png'),
//Add other images here
}
and here’s the RestaurantCard component :
export default function RestaurantCard({ item }) {
const width = 140;
const height = 100;
// Get the image dynamically from the images object
const Logo = Image.resolveAssetSource(images[item.image]).uri;
return (
<Pressable style={{ marginVertical: 4, justifyContent: 'center', alignItems: 'center', backgroundColor: '#c8c8c8', borderRadius: 16 }}
onPress={() => console.log(`Clicked on ${item.name}`)}>
<View style={{ width: width, height: height, backgroundColor: 'black', borderRadius: 16 }}>
<Image source={{uri: Logo}} style={{ width: width, height: height, resizeMode: 'stretch', borderRadius: 16 }} />
</View>
<FontAwesome name='circle' size={38} color={'#aaa'} style={{ position: 'absolute', bottom: 26 }} />
<Ionicons name='fast-food-outline' size={24} style={{ position: 'absolute', bottom: 32, color: '#ddd' }} />
<Text className='font-semibold text-gray-600 text-lg mt-5'>{item.name}</Text>
</Pressable>
);
}
!! Ensure that the image field in your JSON data matches the filenames exactly, for example: “kfc”
1