React Native: require() with Dynamic String?
As i have heard of, react's require()
only uses static url not variables, that means that you have to do require('/path/file')
, take a look at this issue on github and this one for more alternative solutions, there are a couple of other ways to do it!for e.g
const images = {profile: { profile: require('./profile/profile.png'), comments: require('./profile/comments.png'),}, image1: require('./image1.jpg'), image2: require('./image2.jpg'),};export default images;
then
import Images from './img/index';render() { <Image source={Images.profile.comments} />}
from this answer
Here is my solution.
Setup
File structure:
app |--src |--assets |--images |--logos |--small_kl_logo.png |--small_a1_logo.png |--small_kc_logo.png |--small_nv_logo.png |--small_other_logo.png |--index.js |--SearchableList.js
In index.js
, I have this:
const images = { logos: { kl: require('./logos/small_kl_logo.png'), a1: require('./logos/small_a1_logo.png'), kc: require('./logos/small_kc_logo.png'), nv: require('./logos/small_nv_logo.png'), other: require('./logos/small_other_logo.png'), }};export default images;
In my SearchableList.js
component, I then imported the Images component like this:
import Images from './assets/images';
I then created a new function imageSelect
in my component:
imageSelect = network => { if (network === null) { return Images.logos.other; } const networkArray = { 'KL': Images.logos.kl, 'A1': Images.logos.a1, 'KC': Images.logos.kc, 'NV': Images.logos.nv, 'Other': Images.logos.other, }; return networkArray[network];};
Then in my components render
function I call this new imageSelect
function to dynamically assign the desired Image based on the value in the this.state.network
:
render() { <Image source={this.imageSelect(this.state.network)} />}
The value passed into the imageSelect function could be any dynamic string. I just chose to have it set in the state first and then passed in.
I hope this answer helps. :)
For anyone reading this that cannot work with the existing answers, I have an alternative.
First I'll explain my scenario. We have a mono repo with a number of packages (large react-native app). I want to dynamically import a bunch of locale files for i18n without having to keep a central registry in some magic file. There could be a number of teams working in the same monorepo and the DX we want is for package developers to be able to just add their local files in a known folder {{packageName}}/locales/en.json
and have our core i18n functionality pick up their strings.
After several less than ideal solutions, I finally landed on https://github.com/kentcdodds/babel-plugin-preval as an ideal solution for us. This is how I did it:
const packageEnFiles = preval` const fs = require('fs'); const path = require('path'); const paths = []; const pathToPackages = path.join(__dirname, '../../../../packages/');fs.readdirSync(pathToPackages) .filter(name => fs.lstatSync(path.join(pathToPackages, name)).isDirectory()) .forEach(dir => { if (fs.readdirSync(path.join(pathToPackages, dir)).find(name => name === 'locales')) { const rawContents = fs.readFileSync(path.join(pathToPackages, dir, 'locales/en.json'), 'utf8'); paths.push({ name: dir, contents: JSON.parse(rawContents), }); } }); module.exports = paths;`;
Then I can just iterate over this list and add the local files to i18next:
packageEnFiles.forEach(file => { i18n.addResourceBundle('en', file.name, file.contents);});