wake-up-neo.com

reakt.js Ersetzen Sie img src onerror

Ich habe eine React-Komponente, die die Detailansicht einer Liste darstellt.

Ich versuche, das Bild durch ein Standardbild zu ersetzen, wenn das Bild nicht vorhanden ist und ein Fehler 404 auftritt. 

Normalerweise würde ich die onerror-Methode im img-Tag verwenden, aber das scheint nicht zu funktionieren.

Ich bin mir nicht sicher, wie ich das machen soll.

Hier ist meine Komponente:

import React from 'react';
import {Link} from 'react-router';
import ContactStore from '../stores/ContactStore'
import ContactActions from '../actions/ContactActions';

class Contact extends React.Component {
  constructor(props) {
    super(props);
    this.state = ContactStore.getState();
    this.onChange = this.onChange.bind(this); 
 }

componentDidMount() {
  ContactStore.listen(this.onChange);
  ContactActions.getContact(this.props.params.id);
}

componentWillUnmount() {
  ContactStore.unlisten(this.onChange);
}

componentDidUpdate(prevProps) {
  if (prevProps.params.id !== this.props.params.id) {
    ContactActions.getContact(this.props.params.id);
  }
}

onChange(state) {
  this.setState(state);
}

render() {
  return (
    <div className='container'>
      <div className='list-group'>
        <div className='list-group-item animated fadeIn'>
          <h4>{this.state.contact.displayname}</h4>
          <img src={this.state.imageUrl} />
        </div>
      </div>
    </div>
  );
}
}

export default Contact;
26
Joel Lawler

Das funktioniert am besten für mich

<img src={record.picture} onError={(e)=>{e.target.onerror = null; e.target.src="image_path_here"}}/>
57
Deepak Mallah

Sie können eine unkontrollierte Komponente verwenden:

<img src={this.state.img} ref={img => this.img = img} onError={
    () => this.img.src = 'img/default.img'
}>
9
K.Arthur

Sie müssen nur den onError-Handler definieren, als den Status zu ändern, der die Komponententrendemethode auslöst, und schließlich wird die Komponente mit Platzhalter erneut gerendert.

Bitte verwenden Sie nicht jQuery und React zusammen!

import React from 'react';
import {Link} from 'react-router';
import ContactStore from '../stores/ContactStore'
import ContactActions from '../actions/ContactActions';

class Contact extends React.Component {
  constructor(props) {
    super(props);
    this.state = ContactStore.getState();
    this.onChange = this.onChange.bind(this); 
 }

componentDidMount() {
  ContactStore.listen(this.onChange);
  ContactActions.getContact(this.props.params.id);
}

componentWillUnmount() {
  ContactStore.unlisten(this.onChange);
}

componentDidUpdate(prevProps) {
  if (prevProps.params.id !== this.props.params.id) {
    ContactActions.getContact(this.props.params.id);
  }
}

onChange(state) {
  this.setState(state);
}

onError() {
  this.setState({
    imageUrl: "img/default.png"
  })
}

render() {
  return (
    <div className='container'>
      <div className='list-group'>
        <div className='list-group-item animated fadeIn'>
          <h4>{this.state.contact.displayname}</h4>
          <img onError={this.onError.bind(this)} src={this.state.imageUrl} />
        </div>
      </div>
    </div>
  );
}

export default Contact;
6
Skay

Arthurs Antwort führt zu unendlichen Rückrufen, wenn das Fallback-Image ebenfalls fehlschlägt.

Um dies zu vermeiden, setzen Sie zunächst einen Status im Konstruktor für imageLoadError auf true:

constructor(props) {
    super(props);
    this.state = {
      imageLoadError: true,
    };
}

und prüfen Sie dann diesen Statuswert in der Funktion onError, um unendliche Rückrufe zu vermeiden. 

Der Code sieht so aus: -

<img
    src={"https://if_this_url_fails_go_to_onError"}
    onError={e => { 
        if(this.state.imageLoadError) { 
        this.setState({
            imageLoadError: false
        });
        e.target.src = 'fallbackImage.png';
    }}
    }
/>
3
Nitesh Ranjan

@ DepHs Antwort ist Nice, aber es erzeugt eine Endlosschleife, falls Ihre Fehlerquelle ebenfalls nicht geladen wird. Dies half mir, die Callback-Schleife zu vermeiden:

onError={(e)=>{ if (e.target.src !== "image_path_here") 
    { e.target.onerror = null; e.target.src="image_path_here"; } }}
2

Ich nahm die Antwort von @ Skay und erstellte eine wiederverwendbare Image-Komponente. Posting, falls es jemandem hilft:

import React, { PropTypes } from 'react';

const Image = ({src, fallbackSrc, ...other}) => {
    let element;
    const changeSrc = newSrc => {
        element.src = newSrc;
    };
    return (
        <img src={src} 
             onError={() => changeSrc(fallbackSrc)} 
             ref={el => element=el} 
             {...other} />
    );
};

Image.propTypes = {
    src: PropTypes.string,
    fallbackSrc: PropTypes.string
};
export default Image;

2
Kevin

Ich hatte ein ähnliches Problem und die beste Lösung, die ich finden konnte, war die Antwort von Georgii Oleinikov . (Erfordert keine neuen imageLoadError-Zustände, wie von Nitesh Ranjan in seiner Antwort vorgeschlagen)

onError={(e)=>{ if (e.target.src !== "image_path_here"){
                    e.target.onerror = null;
                     e.target.src="image_path_here";}
                }
           }

e.target.onerror = null wird nicht benötigt (und hilft auch nicht wirklich), da die if-Bedingung ausreicht, um die Endlosschleife zu verhindern (falls das Backup-Image ebenfalls nicht geladen wird).

So:

onError={(e)=>{ if (e.target.src !== "image_path_here"){
                 e.target.src="image_path_here";}
               }
         }

BEARBEITEN: Die andere Möglichkeit besteht darin, ein Flag außerhalb der zurückgegebenen Klammern zu setzen und das Flag in der if-Anweisung zu überprüfen. Code sollte ungefähr so ​​aussehen:

render(){
 let errorflag=true;
 return(
            <img alt='' src={imageUrl} 
                    onError={(e)=>{ if (errorflag){ errorflag=false; e.target.src=url; } }} />
            );
} 
2
Saurabh Chauhan
import OriginalImage from '../../originalImg.png'
import ReplacementImage from '../../replaceImg.png'

<img
 src= OriginalImage
 alt="example"
 onError={(e) => {
    e.target.src = ReplacementImage //replacement image imported above
    e.target.style = 'padding: 8px; margin: 16px' // inline styles in html format
 }}
/>

das verwende ich gerade.

1
Mrinmay

Für diejenigen wie mich, die auch die Stile des Elements und/oder die Quelle img ändern wollten, tun Sie einfach Folgendes:

<img
  src={'original src url goes here'}
  alt="example"
  onError={(e) => {
     e.target.src = '/example/noimage.png' // some replacement image
     e.target.style = 'padding: 8px; margin: 16px' // inline styles in html format
  }}
/>

Ich hoffe es hilft!

1
Gustavo Garcia

Sie können object verwenden, wenn dies für Ihre Anforderung in Ordnung ist. Etwas wie unten wird perfekt funktionieren

<object data={expected_image} type="image/jpg">
  <img src={DEFAULT} alt="404" />
</object>

Weitere Informationen finden Sie in dieser Antwort https://stackoverflow.com/a/29111371/1334182

0
S4beR

So habe ich es gemacht. 

 class Pix extends React.Component{

          constructor(props){
            super(props);
           this.state={link: this.props.link};
           this.onError=this.onError.bind(this);
          }


          onError(){
              console.log("error: could not find picture");
              this.setState(function(){ return {link: "missing.png"}; });
             };

          render(){
          return <img onError={this.onError} src={this.state.link}/>;
          } 
    }
0
Matthias Liszt

Hier ist eine Antwort mit Haken:

import React, { useState } from 'react'

/**
 * Returns an object that can 
 * be spread onto an img tag
 * @param {String} img
 * @param {String} fallback
 * @returns {Object} { src: String, onError: Func }
*/
function useFallbackImg(img, fallback) {
  const [src, setImg] = useState(img)

  function onError(e) {
    console.log('Missing img', img, e)
    // React bails out of hook renders if the state
    // is the same as the previous state, otherwise
    // fallback erroring out would cause an infinite loop
    setImg(fallback)
  }

  return { src, onError }
}

/**
 * Usage <Image src='someUrl' fallback='fallbackUrl' alt='something' />
 */
function Image({src, fallback, ...rest}) {

  const imgProps = useFallbackImg(src, fallback)

  return <img {...imgProps} {...rest} />
}

Und wenn Sie mit dem Ändern der Requisite src umgehen möchten, können Sie eine Requisite key der Requisite src übergeben. https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html#recommendation-fully-uncontrolled-component-with-a-key

<Image key='someUrl' src='someUrl' fallback='fallbackUrl' alt='...' />

Der einzige extrem konstruierte Edge-Fall, bei dem die Verwendung eines solchen Schlüssels fehlschlagen könnte, ist die Verwendung von Geschwisterkomponenten. Ich denke, nur ein Geschwisterknoten wird gerendert, wenn er denselben Schlüssel hat. Um dies zu umgehen, könnten Sie das Bild wahrscheinlich in einen <>Fragment einwickeln.

<><Image key={srcProp} ... /></>
<><Image key={srcProp} ... /></>
0
jtc

Ich habe so geschrieben.

import React, { useState } from 'react';
import NoImageSVG from './noImage.svg';

const ImgWithFallback: React.FunctionComponent<{ src: string; alt: string; className: string }> = ({
  src,
  alt,
  className,
}) => {
  const [isUndefined, updateIsUndefined] = useState(false);

  const onError = () => {
    updateIsUndefined(true);
  };

  if (isUndefined) {
    return (
      <div className={className}>
        <NoImageSVG width='5rem' height='5rem' />
      </div>
    );
  }

  return <img src={src} alt={alt} className={className} onError={onError} />;
};

export default React.memo(ImgWithFallback, () => true);

0
R. M.

Da es keine perfekte Antwort gibt, poste ich den Ausschnitt, den ich benutze. Ich verwende eine wiederverwendbare Image-Komponente, die auf fallbackSrc zurückgreift.

Da das Fallback-Image erneut fehlschlagen und eine unendliche Schleife für das erneute Rendern auslösen könnte, habe ich den Status errored hinzugefügt.

import React, { Component } from 'react';
import PropTypes from 'prop-types';

class Image extends Component {
  constructor(props) {
    super(props);

    this.state = {
      src: props.src,
      errored: false,
    };
  }

  onError = () => {
    if (!this.state.errored) {
      this.setState({
        src: this.props.fallbackSrc,
        errored: true,
      });
    }
  }

  render() {
    const { src } = this.state;
    const {
      src: _1,
      fallbackSrc: _2,
      ...props
    } = this.props;

    return (
      <img
        src={src}
        onError={this.onError}
        {...props}
      />
    );
  }
}

Image.propTypes = {
  src: PropTypes.string,
  fallbackSrc: PropTypes.string,
};

0
emil