admin管理员组

文章数量:1136533

I have read several posts about issues that people are having with React Native and the require() function when trying to require a dynamic resource such as:

Dynamic (fails):

urlName = "sampleData.json";
data = require('../' + urlName);

vs. Static (succeeds):

data = require('../sampleData.json');

I have read on some threads that this is a bug in React Native and in others that this is a feature.

Is there a new way to require a dynamic resource within a function?

Related Posts (all fairly old in React time):

  • Importing Text from local json file in React native
  • React Native - Dynamically List/Require Files In Directory
  • React Native - Image Require Module using Dynamic Names
  • React Native: how to use require(path) with dynamic urls?

I have read several posts about issues that people are having with React Native and the require() function when trying to require a dynamic resource such as:

Dynamic (fails):

urlName = "sampleData.json";
data = require('../' + urlName);

vs. Static (succeeds):

data = require('../sampleData.json');

I have read on some threads that this is a bug in React Native and in others that this is a feature.

Is there a new way to require a dynamic resource within a function?

Related Posts (all fairly old in React time):

  • Importing Text from local json file in React native
  • React Native - Dynamically List/Require Files In Directory
  • React Native - Image Require Module using Dynamic Names
  • React Native: how to use require(path) with dynamic urls?
Share Improve this question asked Jul 8, 2017 at 23:32 Jake ChasanJake Chasan 6,5409 gold badges48 silver badges92 bronze badges
Add a comment  | 

11 Answers 11

Reset to default 45

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);
});

I have found that a dynamic path for require() works when it starts with a static string. For example require("./" + path) works, whereas require(path) doesn't.

If you need to switch between multiple locally stored images, you can also use this way:

        var titleImg;
        var textColor;
        switch (this.props.data.title) {
        case 'Футбол':
            titleImg = require('../res/soccer.png');
            textColor = '#76a963';
            break;
        case 'Баскетбол':
            titleImg = require('../res/basketball.png');
            textColor = '#d47b19';
            break;
        case 'Хоккей':
            titleImg = require('../res/hockey.png');
            textColor = '#3381d0';
            break;
        case 'Теннис':
            titleImg = require('../res/tennis.png');
            textColor = '#d6b031';
            break;
        }

In this snippet I change variables titleImg and textColor depending of the prop. I have put this snippet directly in render() method.

Simple to dynamic images (using require)

Example array(into state)

this.state={
       newimage: require('../../../src/assets/group/kids_room.png'),
       randomImages=[
         {
            image:require('../../../src/assets/group/kids_room.png')
          },
         {
            image:require('../../../src/assets/group/kids_room2.png')
          }
        ,
         {
            image:require('../../../src/assets/group/kids_room3.png')
          }
        
        
        ]

}

Trigger image( like when press button(i select image random number betwenn 0-2))

let setImage=>(){

this.setState({newimage:this.state.randomImages[Math.floor(Math.random() * 3)];
})
}

view

<Image
        style={{  width: 30, height: 30 ,zIndex: 500 }}
        
        source={this.state.newimage}
      />

Hey lads I rounded another way to require It's ugly but works. Images dynamically. Instead of storing your URL in the state you store the entire JSX. For an example:

state = {
  image: []
};

Instead of

let imageURL = `'../assets/myImage.png'`
this.state.image = imageURL

You use

let greatImage = (<Image source={require(../assets/myImage.png)}></Image>)
this.state.image = greatImage

To render in the JSX

{this.state.image}

You can style your image in the variable too. I had to use some if statements to render some images dynamically and after break my head for 2 hours this was the way that solved my problem. Like I said It's ugly and probably wrong.

Try the solution mentioned in this thread for Android. This solves the issue but unfortunately, it's only for android.

But make sure to run react-native run-android after every update. Else, the added images won't appear in the app.

Are you using a module bundler like webpack?

If so, you can try require.ensure()

See: https://webpack.js.org/guides/code-splitting/#dynamic-imports

Reading through the docs, I've found a working answer and I'm able to use dynamic images, in the docs they refer to it as Network Images here

https://facebook.github.io/react-native/docs/images#network-images

Not sure if this can be applied to other file types, but as they list require with non image types

You would need to use the uri: call

data = {uri: urlName}

For me I got images working dynamically with this

<Image source={{uri: image}} />

This seems to work :

const {
      messages,
    } = require(`../${dynamicPath}/messages.specific`);

本文标签: javascriptReact Native require() with Dynamic StringStack Overflow