web-dev-qa-db-ja.com

SVG画像のフォルダー全体をインポートする方法(またはそれらを動的に読み込む方法)をReact Web App?

: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 svgを含める必要があるため、余分なコードが大量に追加されます。

また、私は この質問で このコードを見つけました...

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を見つけることができません。 「./images/」も試しました

最後の重要な情報を1つだけ紛失しているように感じます。過去1日を検索した後、誰かが紛失している部分を特定できることを望んでいました。

15
WiseOlMan

Reactを使用している場合、Webpackも使用していると強く思います。 es6 importの代わりに require.context を使用すると、Webpackがビルド時に自動的に解決します。

require.context ( folder, recurse, pattern )
  • folder-文字列-ファイルのスキャンを開始するフォルダーへのパス。
  • recurse-ブール値-フォルダーを再帰的にスキャンするかどうか。
  • pattern-RegExp-含めるファイルを説明する一致パターン。

各例の最初の行...

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

... imagesフォルダー内のすべての*.svgファイルパスをインポートにマッピングするRequire Contextを作成します。これにより、reqSvgsという名前の特殊なRequire関数と、いくつかのプロパティが付加されます。

reqSvgsのプロパティの1つはkeysメソッドで、すべての有効なファイルパスのリストを返します。

const allSvgFilepaths = reqSvgs.keys ()

これらのファイルパスの1つをreqSvgsに渡して、インポートされたイメージを取得できます。

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

オブジェクトの配列

オブジェクトの配列を作成します。各オブジェクトは1つの画像に対して{ 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のより一般化された例を提供します SurviveJS Webpack Dynamic Loading

11
skylize

複数のSVGファイルの代わりに、単一のSVGスプライトを使用できます。

SVG Spriteは、SVGファイルのディレクトリから svg-Sprite-generator を使用して生成できます。

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>
)
2
quotesBro

最良の方法は、[SVG to React Loader]などのノードモジュールを使用することです(- https://github.com/jhamlet/svg-react-loader

1
karthik

パラメーター "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>
  )
}
0
madhurgarg

この問題につまずいた-私は最初に「受け入れられた答え」を持っていましたが、私はレート制限を引き起こしたすべてのsvgのhttpリクエストを引き起こしました。だから私は受け入れられた答えと@karthikが提案したものの組み合わせになりました-request.contextでローダーを使用する

CRA 2.0の時点で、svgを反応コンポーネントとしてインポートするために@svgrが含まれています。

const reqSvgs = require.context('!@svgr/webpack!flag-icon-css/flags/4x3', true, /\.svg$/)

したがって、ここではsvgローダーとrequire.contextを組み合わせます

const flagMap = reqSvgs.keys().reduce((images, path) => {
  const key = path.substring(path.lastIndexOf('/') + 1, path.lastIndexOf('.'))
  images[key] = reqSvgs(path).default
  return images
}, {})

次に、これらすべてをjsonオブジェクトにマッピングして、キールックアップを使用できるようにします

Jsxでsvgをレンダリングするには:

const Flag = flagMap['dk']
return (
  <Flag />
)

そして幸せな日、svgはバンドルに含まれ、個々のhttpリクエストはありません????????

0
Christian