Many students struggle to dynamically display images in React Native, and often attempt to use require along with props to dynamically source images. However, this is incompatible with dynamic paths because Expo pre-bundles all assets at build time, making dynamic loading at runtime with require impossible, and using require only works with static images. This results in the following error:
error: app/user/[id].tsx: app/user/[id].tsx:Invalid call at line 27: require(`../../assets/upleveled-${id}.jpeg`)
ERROR [Error: TransformError app/user/[id].tsx: app/user/[id].tsx:Invalid call at line 27: require(`../../assets/upleveled-${id}.jpeg`)]
Error: app/user/[id].tsx:Invalid call at line 27: require(`../../assets/upleveled-${id}.jpeg`)
at transformJS (/Users/lukas/Documents/projects/upleveled-react-native-expo/register-login/node_modules/@expo/metro-config/build/transform-worker/metro-transform-worker.js:228:23)
at transformJSWithBabel (/Users/lukas/Documents/projects/upleveled-react-native-expo/register-login/node_modules/@expo/metro-config/build/transform-worker/metro-transform-worker.js:316:18)
Solution
To address this issue, we should teach students how to dynamically display images in React Native using best practices.
The recommended solution for me is to use direct URLs to the images and use the image URL in the source attribute. In React Native, the source attribute expects an object containing the uri attribute rather than a string. By following this method, students can dynamically use images and display them within the app using the uri attribute.
<Image source={{uri: props.imageUrl}} />
This approach is simple and effective and helps students overcome the challenges of dynamically displaying images in their React Native apps. Key benefits include:
simple and easy to understand, and students can easily implement it
smaller App size, as images are not bundled with the app
As an image host, I would recommend to use Cloudinary. There are also other image hosting services, but Cloudinary is very popular and offers a free tier that students can use to host their images.
Alternative Solutions
Using require.context
Using require.context to dynamically import images based on a regular expression pattern matching image filenames. This usage of require.context will throw a TS error Property 'context' does not exist on type 'NodeRequire'., for this issue we can add @types/webpack-env package to resolve this error.
Pros:
Provides a way to dynamically import images based on a regular expression pattern
Allows for dynamic loading of images at runtime
Cons:
Requires additional setup and may introduce complexity
Express Static File Serving, which involves setting up a server to serve static files. However, this is more complex and requires more setup, also using Express, and not the Expo API Routes
Pros:
Offers a solution for serving static files in a server-side application
Cons:
More complex and requires additional setup, involving setting up a server with Express
File with require image paths
This involves creating an assets/index.js file where image paths are defined as variables, or defined as an object. Students can then import this variable and use the imported variable for the require statement. While this approach works, it's considered less optimal compared to using direct URLs.
Pros:
Provides a way to organize image paths in a central file for easy management
Works well for static paths that don't need to be dynamically generated
Cons:
Requires manual updating of the file when adding or removing images
Introduce complexity and potential maintenance overhead
Takeover from https://github.com/hola-soy-milk/upleveled-react-native-expo/issues/14
Many students struggle to dynamically display images in React Native, and often attempt to use
require
along withprops
to dynamically source images. However, this is incompatible with dynamic paths because Expo pre-bundles all assets at build time, making dynamic loading at runtime with require impossible, and usingrequire
only works with static images. This results in the following error:Solution
To address this issue, we should teach students how to dynamically display images in React Native using best practices.
The recommended solution for me is to use direct URLs to the images and use the image URL in the
source
attribute. In React Native, thesource
attribute expects anobject
containing theuri
attribute rather than astring
. By following this method, students can dynamically use images and display them within the app using theuri
attribute.This approach is simple and effective and helps students overcome the challenges of dynamically displaying images in their React Native apps. Key benefits include:
As an image host, I would recommend to use Cloudinary. There are also other image hosting services, but Cloudinary is very popular and offers a free tier that students can use to host their images.
Alternative Solutions
Using
require.context
Using
require.context
to dynamically import images based on a regular expression pattern matching image filenames. This usage ofrequire.context
will throw a TS errorProperty 'context' does not exist on type 'NodeRequire'.
, for this issue we can add@types/webpack-env
package to resolve this error.Pros:
Cons:
Express Static File Serving
Express Static File Serving, which involves setting up a server to serve static files. However, this is more complex and requires more setup, also using Express, and not the Expo API Routes
Pros:
Cons:
File with
require
image pathsThis involves creating an
assets/index.js
file where image paths are defined as variables, or defined as anobject
. Students can then import this variable and use the imported variable for therequire
statement. While this approach works, it's considered less optimal compared to using direct URLs.Pros:
Cons:
assets/index.js
app/index.js
Import function
Function to import all images from a directory and use the imported images object to dynamically select the image based on the
id
.Pros:
Cons: