React Native:require()with Dynamic String?

时间:2017-07-08 23:32:14

标签: javascript reactjs react-native ecmascript-6 require

在尝试要求动态资源时,我已经阅读了几篇关于人们使用React Native和require()函数的帖子的文章:

动态(失败)

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

VS。静态(成功)

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

我已经阅读了一些线程,这是React Native中的一个错误,而在其他线程中,这是一个功能。

是否有一种新方法可以在函数中要求动态资源?

相关帖子(React时间都相当旧):

10 个答案:

答案 0 :(得分:7)

正如我所听到的,反应require()仅使用静态网址而非变量,这意味着您必须require('/path/file'),请查看此issue on github和{{3}对于更多替代解决方案,还有其他几种方法可以做到! 例如

const images = {
profile: {
    profile: require('./profile/profile.png'),
    comments: require('./profile/comments.png'),
},
   image1: require('./image1.jpg'),
   image2: require('./image2.jpg'),
};

export default images;

然后

import Images from './img/index';

render() {
    <Image source={Images.profile.comments} />
}

来自this one

答案 1 :(得分:2)

嘿,伙计们,我采用了另一种方式来要求它丑陋但有效。动态图像。不是将 URL 存储在状态中,而是存储整个 JSX。例如:

state = {
  image: []
};

代替

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

你使用

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

在 JSX 中渲染

{this.state.image}

您也可以在变量中设置图像样式。我不得不使用一些 if 语句来动态渲染一些图像,在我头昏脑胀 2 小时后,这就是解决我问题的方法。就像我说的那样丑陋而且可能是错误的。

答案 2 :(得分:1)

这是我的解决方法。

设置

文件结构:

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

index.js中,我有这个:

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;

在我的SearchableList.js组件中,然后像这样导入Images组件:

import Images from './assets/images';

然后我在组件中创建了一个新函数imageSelect

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

然后在我的组件render函数中,我将此新的imageSelect函数称为根据this.state.network中的值动态分配所需的图像:

render() {
  <Image source={this.imageSelect(this.state.network)} />
}

传递给imageSelect函数的值可以是任何动态字符串。我只是选择先将其设置为状态,然后再传递。

我希望这个答案会有所帮助。 :)

答案 3 :(得分:1)

我发现 require() 的动态路径在以静态字符串开头时有效。例如,require("./" + path) 有效,而 require(path) 无效。

答案 4 :(得分:0)

您使用的是像webpack这样的模块捆绑器吗?

如果有,您可以尝试require.ensure()

请参阅:https://webpack.js.org/guides/code-splitting/#dynamic-imports

答案 5 :(得分:0)

如果您需要在多个本地存储的图像之间切换,您也可以使用这种方式:

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

在此代码段中,我根据道具更改变量titleImgtextColor。我已将此代码段直接放在render()方法中。

答案 6 :(得分:0)

通读文档,我找到了一个可行的答案,并且能够使用动态图像,在文档中,他们将其称为“网络图像”

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

不确定是否可以将其应用于其他文件类型,但因为它们列出了非图像类型的要求

您需要使用uri:呼叫

data = {uri: urlName}

对我来说,我可以使图像动态工作

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

答案 7 :(得分:0)

尝试使用this主题中提到的Android解决方案。这样就可以解决问题,但不幸的是,它仅适用于android。

但是请确保在每次更新后运行react-native run-android。否则,添加的图像将不会出现在应用程序中。

答案 8 :(得分:0)

对于阅读本文无法解决现有答案的任何人,我都有另一种选择。

首先,我将说明我的情况。我们有一个带有许多软件包的单声道仓库(大型react-native应用程序)。我想为i18n动态导入一堆语言环境文件,而不必在某些魔术文件中保留中央注册表。可能会有许多团队在同一个monorepo中工作,而我们想要的DX是让软件包开发人员能够将其本地文件添加到已知文件夹{{packageName}}/locales/en.json中,并使我们的核心i18n功能能够提取字符串。

经过几次不理想的解决方案之后,我终于落入https://github.com/kentcdodds/babel-plugin-preval作为对我们来说是理想的解决方案。这是我的方法:

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;
`;

然后我可以遍历此列表并将本地文件添加到i18next:

packageEnFiles.forEach(file => {
  i18n.addResourceBundle('en', file.name, file.contents);
});

答案 9 :(得分:0)

简单到动态图像(使用require)

示例数组(进入状态)

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')
          }
        
        
        ]

}

触发图像(如按下按钮时(我选择0-2之间的图像随机数))

let setImage=>(){

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

视图

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