J'ai un composant de réaction qui est la vue détaillée d'une liste.
J'essaie de remplacer l'image par une image par défaut si l'image n'existe pas et qu'il y a une erreur 404.
J'utiliserais normalement la méthode onerror dans la balise img, mais cela ne semble pas fonctionner.
Je ne sais pas comment faire avec Réagir.
Voici mon composant:
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;
Cela fonctionne mieux pour moi
<img src={record.picture} onError={(e)=>{e.target.onerror = null; e.target.src="image_path_here"}}/>
Vous pouvez utiliser un composant non contrôlé:
<img src={this.state.img} ref={img => this.img = img} onError={
() => this.img.src = 'img/default.img'
}>
Vous devez simplement définir le gestionnaire onError avant de modifier l’état qui déclenchera la méthode de rendu du composant et, éventuellement, le composant sera rendu à nouveau avec un espace réservé.
S'il vous plaît, n'utilisez pas jQuery et réagissez ensemble!
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;
La réponse d'Arthur entraînera des rappels infinis si l'image de secours échoue également.
Pour éviter cela, définissez d'abord un état dans le constructeur pour imageLoadError sur true:
constructor(props) {
super(props);
this.state = {
imageLoadError: true,
};
}
puis recherchez cette valeur d'état dans la fonction onError
pour éviter des rappels infinis,
le code ressemblera à ceci: -
<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';
}}
}
/>
La réponse de @ DepH est Nice, mais elle produit une boucle infinie si votre source d'erreur ne se charge pas non plus. Cela m'a aidé à éviter la boucle de rappel:
onError={(e)=>{ if (e.target.src !== "image_path_here")
{ e.target.onerror = null; e.target.src="image_path_here"; } }}
J'ai pris la réponse de @ Skay et créé un composant Image réutilisable. Publier au cas où cela aiderait quelqu'un:
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;
Couru dans un problème similaire et la meilleure solution que j'ai pu trouver était la réponse de Georgii Oleinikov . (Ne nécessite pas de créer un nouvel état imageLoadError
comme suggéré par Nitesh Ranjan dans sa réponse)
onError={(e)=>{ if (e.target.src !== "image_path_here"){
e.target.onerror = null;
e.target.src="image_path_here";}
}
}
e.target.onerror = null
n'est pas nécessaire (et n'aide pas vraiment) car la condition if suffit à empêcher la boucle infinie (si le chargement de l'image de sauvegarde échoue également).
Alors:
onError={(e)=>{ if (e.target.src !== "image_path_here"){
e.target.src="image_path_here";}
}
}
EDIT: L’inverse est de placer un drapeau en dehors des crochets et de vérifier le drapeau dans l’instruction if. Le code devrait ressembler à ceci:
render(){
let errorflag=true;
return(
<img alt='' src={imageUrl}
onError={(e)=>{ if (errorflag){ errorflag=false; e.target.src=url; } }} />
);
}
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
}}
/>
c'est ce que j'utilise actuellement.
Pour ceux qui, comme moi, souhaitent également modifier les styles de l'élément et/ou modifier la source img, procédez comme suit:
<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
}}
/>
J'espère que ça aide!
Vous pouvez utiliser object
si cela vous convient. Quelque chose comme ci-dessous fonctionnera parfaitement bien
<object data={expected_image} type="image/jpg">
<img src={DEFAULT} alt="404" />
</object>
Cochez cette réponse pour plus de détails https://stackoverflow.com/a/29111371/1334182
C'est comme ça que je l'ai fait.
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}/>;
}
}
Puisqu'il n'y a pas de réponse parfaite, je publie l'extrait de code que j'utilise. J'utilise un composant Image
réutilisable qui se replie sur fallbackSrc
.
Comme l'image de repli pouvait à nouveau échouer et déclencher une boucle infinie de restitution, j'ai ajouté l'état errored
.
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,
};