Bilder dynamisch hinzufügen Reagieren Sie auf Webpack

76

Ich habe versucht herauszufinden, wie Bilder über React und Webpack dynamisch hinzugefügt werden können. Ich habe einen Bildordner unter src / images und eine Komponente unter src / components / index . Ich verwende URL-Loader mit der folgenden Konfiguration für Webpack

    {
      test: /\.(png|jpg|)$/,
      loader: 'url-loader?limit=200000'
    }

Innerhalb der Komponente, von der ich weiß, dass ich require (image_path) für ein bestimmtes Bild oben in der Datei hinzufügen kann, bevor ich die Komponente erstelle, möchte ich die Komponente generisch machen und sie eine Eigenschaft mit dem Pfad für das Bild übernehmen lassen, von dem übergeben wird die übergeordnete Komponente.

Was ich versucht habe ist:

<img src={require(this.props.img)} />

Für die eigentliche Eigenschaft habe ich so ziemlich jeden Pfad ausprobiert, den ich mir aus dem Projektstamm, dem React-App-Stamm und der Komponente selbst vorstellen kann.

Dateisystem

|-- src
|   ` app.js
|   `--images
|      ` image.jpg
|      ` image.jpg
|   `-- components
|      `parent_component.js
|      `child_component.js

Die übergeordnete Komponente ist im Grunde genommen nur ein Container, in dem mehrere ...

<ChildComponent img=data.img1 />
<ChildComponent img=data.img2 />
etc....

Gibt es eine Möglichkeit, dies mit React und Webpack mit URL-Loader zu tun, oder gehe ich einfach einen falschen Weg, um dies zu erreichen?

pandorz
quelle

Antworten:

97

Mit dem hier beschriebenen URL-Loader ( SurviveJS - Loading Images ) können Sie ihn dann in Ihrem Code verwenden:

import LogoImg from 'YOUR_PATH/logo.png';

und

<img src={LogoImg}/>

Bearbeiten: Eine Präzision, Bilder werden mit dieser Technik in das js-Archiv eingefügt. Es kann für kleine Bilder wertvoll sein, aber setzen Sie die Technik mit Bedacht ein.

mlorber
quelle
1
Ich möchte wissen, wie dieses Bild von einer API geladen wird, die das Bild zurückgibt.
Das Orakel
3
Ich bin mir nicht sicher: Wenn Sie möchten, dass der Benutzerbrowser das Bild von einer API lädt, hat dies nichts mit Webpack zu tun. Verwenden Sie einfach eine Variable (wahrscheinlich nach einem Aufruf der API definiert) als <img> src. Die Idee hier war, das Bild in Ihre Quellen und Ihr Webpack-Archiv aufzunehmen. (siehe stackoverflow.com/questions/32612912/… )
mlorber
1
Danke, das funktioniert super. Der Artikel, den Sie zitiert haben, erwähnt am Ende auch, wenn Sie React verwenden, dann verwenden Sie babel-plugin-transform-react-jsx-img-import, um den Import automatisch zu generieren. Auf diese Weise können Sie einfach <img src = "YOUR_PATH / logo.png" /> schreiben
Homam Bahrani
Warnung: Der URL-Loader fügt die Bilddatei als Base64-ASCII-Zeichenfolge ein. Dies verringert die Anzahl der Dateizugriffe, die zum Laden einer Seite erforderlich sind, jedoch auf Kosten von mehr Bytes zum Herunterladen. Daher ist es möglicherweise besser, den Dateilader für die Produktion zu verwenden.
Hrabinowitz
Ja, Bilder werden mit dieser Technik eingefügt. Dies hängt vollständig vom Gewicht der Datei ab. Für kleine (Symbole hauptsächlich für mich) kann es wert sein. Ich werde die Antwort bearbeiten
mlorber
22

Wenn Sie Ihren Code auf der Serverseite bündeln, hindert Sie nichts daran, Assets direkt von jsx zu benötigen:

<div>
  <h1>Image</h1>
  <img src={require('./assets/image.png')} />
</div>
James Akwuh
quelle
3
Dies musste ich für meine Situation verwenden, in der ich die Bilddatei erst kenne, wenn die Komponente erstellt wurde. Ich gebe eine imageFilenameRequisite ab und benutze sie dann <img src={require(`./images/${imageFilename}`)} />. Danke fürs Schreiben.
Brendan Moore
1
@BrendanMoore, aber denken Sie daran, dass in Ihrem Fall ein Bundler (z. B. Webpack) alle Bilder aus dem imagesOrdner zum endgültigen Bundle hinzufügt .
James Akwuh
1
Genau das, wonach ich gesucht habe. Danke @JamesAkwuh
Samrat Saha
1
Wenn dies nicht funktioniert, fügen Sie nach require () .default hinzu. Beispiel: Ich verwende wie const src = require(Assets / Images / $ {Name}).default;
master_dodo
11

UPDATE : Dies wurde nur mit serverseitigem Rendering (Universal Javascript) getestet. Hier ist mein Boilerplate .

Mit nur File-Loader können Sie Bilder dynamisch laden. Der Trick besteht darin, ES6-Vorlagenzeichenfolgen zu verwenden, damit Webpack sie abrufen kann:

Dies wird NICHT funktionieren. ::

const myImg = './cute.jpg'
<img src={require(myImg)} />

Um dies zu beheben, verwenden Sie stattdessen einfach Vorlagenzeichenfolgen:

const myImg = './cute.jpg'
<img src={require(`${myImg}`)} />

webpack.config.js:

var HtmlWebpackPlugin =  require('html-webpack-plugin')
var ExtractTextWebpackPlugin = require('extract-text-webpack-plugin')

module.exports = {
  entry : './src/app.js',
  output : {
    path : './dist',
    filename : 'app.bundle.js'
  },
  plugins : [
  new ExtractTextWebpackPlugin('app.bundle.css')],
  module : {
    rules : [{
      test : /\.css$/,
      use : ExtractTextWebpackPlugin.extract({
        fallback : 'style-loader',
        use: 'css-loader'
      })
    },{
      test: /\.js$/,
      exclude: /(node_modules)/,
      loader: 'babel-loader',
      query: {
        presets: ['react','es2015']
      }
    },{
      test : /\.jpg$/,
      exclude: /(node_modules)/,
      loader : 'file-loader'
    }]
  }
}
Marwen Trabelsi
quelle
2
Fehlendes Stück für mich war der Test in der Webpack-Konfiguration. Vielen Dank.
Dean Poulin
8

Wenn Sie nach einer Möglichkeit suchen, alle Ihre Bilder aus dem Bild zu importieren

// Import all images in image folder
function importAll(r) {
    let images = {};
    r.keys().map((item, index) => { images[item.replace('./', '')] = r(item); });
    return images;
}

const images = importAll(require.context('../images', false, /\.(gif|jpe?g|svg)$/));

Dann:

<img src={images['image-01.jpg']}/>

Den Original-Thread finden Sie hier: Importieren Sie Bilder mithilfe von Webpack dynamisch aus einem Verzeichnis

Gabriel Esu
quelle
6

Sie müssen also eine Importanweisung für Ihre übergeordnete Komponente hinzufügen:

class ParentClass extends Component {
  render() {
    const img = require('../images/img.png');
    return (
      <div>
        <ChildClass
          img={img}
        />
      </div>
    );
  }
}

und in der Kinderklasse:

class ChildClass extends Component {
  render() {
    return (
      <div>
          <img
            src={this.props.img}
          />
      </div>
    );
  }
}
MCSLI
quelle
3

Sie binden die Bilder nicht in das Bundle ein. Sie werden über den Browser aufgerufen. So ist es;

var imgSrc = './image/image1.jpg';

return <img src={imgSrc} />
J. Mark Stevens
quelle
3
Aber was ist, wenn Sie das Image zum Zeitpunkt der Erstellung nicht kennen? Was ist, wenn die Bild-URL zur Laufzeit erstellt wird?
JBCP
Das Ziel des von Ihnen verwendeten Loaders besteht darin, KEINE URL in Ihrem Code zu verwenden und das Bild möglicherweise in das Archiv einzubetten, wenn es klein genug ist (bessere Leistungen)
mlorber
2

Hier ist der Code

    import React, { Component } from 'react';
    import logo from './logo.svg';
    import './image.css';
    import Dropdown from 'react-dropdown';
    import axios from 'axios';

    let obj = {};

    class App extends Component {
      constructor(){
        super();
        this.state = {
          selectedFiles: []
        }
        this.fileUploadHandler = this.fileUploadHandler.bind(this);
      }

      fileUploadHandler(file){
        let selectedFiles_ = this.state.selectedFiles;
        selectedFiles_.push(file);
        this.setState({selectedFiles: selectedFiles_});
      }

      render() {
        let Images = this.state.selectedFiles.map(image => {
          <div className = "image_parent">

              <img src={require(image.src)}
              />
          </div>
        });

        return (
            <div className="image-upload images_main">

            <input type="file" onClick={this.fileUploadHandler}/>
            {Images}

            </div>
        );
      }
    }

    export default App;
Tayyeb Mehmood
quelle