在 React 中动态渲染图像非常困难
Posted
技术标签:
【中文标题】在 React 中动态渲染图像非常困难【英文标题】:Rendering image dynamically is so hard in React 【发布时间】:2019-10-29 02:00:02 【问题描述】:在尝试了几个小时的各种方法并检查了每个相关链接之后,我找不到任何合适的方法在 React 中动态呈现图像。
这就是我想要做的。
我有一个对象数组,其中每个对象都有一个名为 name 的属性。我正在使用 map 函数 map 循环遍历这个数组并返回 img 元素的数组,如下所示。
<img className="img-thumbnail" src=require('../../public/images/'+item.name+'.png')/>
其中 item.name 是我要显示的图像文件的名称,为此 require 给我错误“找不到模块”。 此外,我需要实现一些后备选项,而不是显示损坏的图像以防图像文件不存在,我想显示默认图像
这是我尝试过的事情:
在 require 上使用 try 和 catch 块并从 img 元素调用此函数
setImage(data)
try
return require( '../../public/images/'+data+'.png' ) //actual image
catch(err)
console.log(err);
return require('../../public/images/fallback.png'); //fallback
<img className="img-thumbnail" src=this.setImage(item)/>
使用导入,在上述同一个函数内,出现错误 import cannot be called from inside of function
使用 react-image 库。原来它不支持本地图像。
有什么帮助吗?
【问题讨论】:
src="/images/fallback.png"
呢?这更像是一个 webpack 或您正在使用的任何捆绑器的问题,而不是一个 react js 问题恕我直言。
这些图像是否在应用程序中可用(静态和捆绑的一部分)或者这些 uri 是从服务器动态获取的?
@johnnypeter 图片在应用程序内,但我从数据库中获取对象。组件挂载后出现问题,因为在那之后 require 似乎不起作用,并且在目录中仍然存在图像时显示找不到模块
@happysharma 如果您的网址在编译时已知,我添加了一个可以帮助您的答案
您正在静态渲染“动态”图像。如果您的图像是公开的,那么只需通过带有相应 JSX/html 元素的 URL 来获取它们,如果您的图像不是公开的,那么您将不得不异步获取 base64 数据(和 mime 类型),这可以通过“redux”之类的东西来完成-saga”(尽管对于您想要实现的目标而言,这似乎过于复杂)。
【参考方案1】:
以上所有答案都很有帮助,但不幸的是,没有一种方法对我有用。所以再次深入挖掘,我发现 require 给出了错误“找不到模块”,因为在 webpack 捆绑我的代码之后,require 丢失了上下文。这意味着给定的相对路径不再有效。
我需要做的是保留我使用 require.context 所做的上下文;
这是最终的有效代码。
//getting the context of image folder
const imageFolderContext = require.context('realtive/path/to/image/folder')
//function to check if image exist
checkFile(data)
try
let pathToImage = './path/to/image/relative/to/image/folder/context
imageFolderContext(pathToImage) //will check if Image exist
return true //return true if exist
catch(err)return false
//rendering image element dynamically based on item name and if exist or not
<img src=this.checkFile(itemName)?imageFolderContext('path/to/image/relative/to/context'):imageFolderContext('default/image/path/) />
别忘了绑定checkFile函数
【讨论】:
【参考方案2】:在编译期间静态检查需求。 requires 的路径不能是动态的。由于您的捆绑包中有静态图像并且对象映射到其中之一,因此您可以按照以下方式解决问题
const images =
image1: require('local/path/to/image1'),
image2: require('local/path/to/image2'),
image3: require('local/path/to/image3'),
const defaultImage = require('local/path/to/defaultImage');
const Img = ( name ) =>
// here name is the name for the image you get from api..
// This should match with the keys listed the iages object
return <img src=images[name] ? images[name] : defaultImage/>
【讨论】:
它适用于静态图像,但不适用于只有在获取对象后才能形成路径。 @happysharma 因为你所有的图片都是静态的,捆绑在你的应用程序中,你可以通过上述方法将名称映射到路径。【参考方案3】:这里有一个棘手的方法来处理这个问题。使用 react state
检查是否有错误。
如果为真,则显示回退,否则,显示实际图像。
setImage = (data) =>
const image = new Image();
image.src = '../../public/images/'+data+'.png';
this.setState(
hasError: false
)
image.onerror = () =>
this.setState(
hasError: true
)
return image.src;
// into render
this.state.hasError
? <img src="../../public/images/fallback.png" />
: <img className="img-thumbnail" src=this.setImage(item)/>
更新:示例
var image = new Image();
image.src = 'fake.jpg';
image.onerror = () =>
console.log('image doesn t exist');
【讨论】:
你如何检查图像是否存在?因为我无法在组件安装后使用 require 获取图像,尽管图像仍然存在于目录中 如果图片不存在会进入onerror。 函数显示图像存在,但再次需要时显示找不到模块 你不再需要使用 require() 了。 没有它,图像将无法加载。网址不能这样反应,你要么在顶部导入它,要么在 src 中要求。【参考方案4】:我不知道你为什么需要它可以像这样简单地完成。你可以导入这样的东西。像这样导入图片
import fallback from '../../public/images/fallback.png';
对于动态图像,我建议制作一些键值对。例如:
让数据 =
图片1:../../public/images/image1.png
,
图片2:../../public/images/image1.png
并正常导入
渲染中的一些东西
可能是这样的。
render()
return(
<img className="img-thumbnail" src=img?img[type]:fallback/> //something its just refrence(where type is something which you want dynamically add image)
)
【讨论】:
src 不会立即采取路径。您使用 require 或 first import。我的前一个案例,但一旦组件安装我就无法做到这一点以上是关于在 React 中动态渲染图像非常困难的主要内容,如果未能解决你的问题,请参考以下文章