Как импортировать всю папку изображений SVG (или как загружать их динамически) в веб-приложение React?

у меня есть компонент, который принимает: itemName и выплевывает HTML-пакет, содержащий изображение. Изображение отличается для каждого пакета.

вот что у меня есть:

import React, { Component } from 'react';
import { NavLink } from 'react-router-dom';

import SVGInline from "react-svg-inline";

export default (props) => (
  <NavLink className="hex" activeClassName="active" to={'/hex/' + props.itemName}> {React.createElement(SVGInline, {svg: props.itemName})} </NavLink>
)

как я могу заставить этот компонент работать?

Я знаю, что если бы я просто импортировал все мои изображения явно, я мог бы просто назвать мои изображения так...

import SVGInline from "react-svg-inline";
import SASSSVG from "./images/sass.svg";

<NavLink className="hex" activeClassName="active" to="/hex/sass"><SVGInline svg={ SASSSVG } /></NavLink>

это сработает, но поскольку мне нужно включить ~60 svgs, он добавляет много лишнего кода.

также, Я нашел в этом вопросе этот код...

import * as IconID from './icons';

но это, похоже, не работает (это была часть вопроса, а не ответ), и ответ был слишком неспецифичным, чтобы ответить на вопрос, который я задаю.

Я нашел этот вопрос но опять же есть ответ (хотя и не одобренный), в котором больше вопросов, чем ответов. Итак, после установки react-svg я настроил тест, чтобы узнать, работает ли ответ так так...

import React, { Component } from 'react';
import ReactDOM from 'react-dom'
import { NavLink } from 'react-router-dom';
import ReactSVG from 'react-svg'

export default (props) => (
  <NavLink className="hex" activeClassName="active" to={'/hex/' + props.itemName}>
    <ReactSVG
      path={"images/" + props.itemName + ".svg"}
      callback={svg => console.log(svg)}
      className="example"
    />
  </NavLink>
)

но, как и OP этого вопроса, страница не может найти мой svg даже после копирования всей моей папки изображений в мою папку сборки. Я тоже пытался"./ изображения/"

Я чувствую, что мне просто не хватает последнего ключевого фрагмента информации, и после поиска за последний день, я надеялся, что кто-то может идентифицировать кусок, который мне не хватает.

4 ответов


если вы используете React, я сильно подозреваю, что вы также используете Webpack. Вы можете использовать require.context вместо es6 import и Webpack разрешит его для вас при строительстве.

require.context ( folder, recurse, pattern )
    - строка - путь к папке, чтобы начать сканирование файлов.
  • recurse-Boolean - следует ли рекурсивно сканировать папку.
  • pattern-RegExp-соответствующий шаблон, описывающий, какие файлы включать.

первая строка каждого примера ...

const reqSvgs = require.context ( './images', true, /\.svg$/ )

... создает требуемое контекстное сопоставление всех *.svg пути к файлам в images папка для импорта. Это дает нам специализированную функцию Require с именем reqSvgs С некоторыми вложенными свойствами.

одно из свойств reqSvgs это keys метод, который возвращает список всех допустимых путей к файлам.

const allSvgFilepaths = reqSvgs.keys ()

мы можем передать один из этих filepaths в reqSvgs to получить импортированное изображение.

const imagePath = allSvgFilePaths[0]
const image = reqSvgs ( imagePath )

этот api является сдерживающим и неинтуитивным для этого случая использования, поэтому я предлагаю преобразовать коллекцию в более распространенную структуру данных JavaScript, чтобы упростить ее работу.

каждое изображение будет импортировано во время преобразования. Осторожнее, это может быть ножной пистолет. Но он предоставляет достаточно простой механизм для копирования нескольких файлов в папку сборки, на которую может никогда не ссылаться остальная часть ваш исходный код.

вот 3 примера преобразований, которые могут быть полезны.


массив

создайте массив импортированных файлов.

const reqSvgs = require.context ( './images', true, /\.svg$/ )
const paths = reqSvgs.keys ()

const svgs = paths.map( path => reqSvgs ( path ) )

массив объектов

создайте массив объектов, причем каждый объект будет { path, file } для одного изображения.

const reqSvgs = require.context ( './images', true, /\.svg$/ )

const svgs = reqSvgs
  .keys ()
  .map ( path => { path, file: svg ( path ) } )

Простой Объект

создайте объект, где каждый путь является ключом к соответствующему файлу.

const reqSvgs = require.context ('./images', true, /\.svg$/ )

const svgs = reqSvgs
  .keys ()
  .reduce ( ( images, path ) => {
    images[path] = reqSvgs ( path )
    return images
  }, {} )

SurviveJS дает более обобщенный пример require.context здесь Динамическая Загрузка Webpack SurviveJS.


вместо нескольких SVG-файлов вы можете использовать один SVG-спрайт.

SVG sprite может быть сгенерирован из каталога SVG-файлов с помощью svg-спрайт-генератор:

svg-sprite-generate -d images -o images/sprite.svg

тогда используйте его так:

import React from 'react';
import { NavLink } from 'react-router-dom';
import sprite from './images/sprite.svg';

export default (props) => (
  <NavLink className="hex" activeClassName="active" to={'/hex/' + props.itemName}>
    <svg xmlns="http://www.w3.org/2000/svg" width="30" height="30">
      <use xlinkHref={`${sprite}#${props.itemName}`} />
    </svg>
  </NavLink>
)

вы можете просто сделать функцию, которая принимает параметр "name" (ваше имя значка svg) и возвращает ваш svg-код.

import React from 'react' export function getIcon(name){ switch(name) { case 'back': return ( // your svg code here <svg></svg> ) } }

и затем вы можете импортировать его в любом месте и просто вызвать его с именем значка вы хотите.

import { getIcon } from './utils'
render() {
  return (
    <div>
     <span>{ getIcon('back') }</span>
    </div>
  )
}

лучший способ-использовать модуль узла, такой как [SVG to React Loader] (https://github.com/jhamlet/svg-react-loader)