Javascript react.js 替换 img src onerror

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/34097560/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 15:55:13  来源:igfitidea点击:

react.js Replace img src onerror

javascriptreactjshttp-status-code-404

提问by Joel Lawler

I have a react component that is the detail view from a list.

我有一个反应组件,它是列表中的详细视图。

I am trying to replace the image with a default image if the image does not exist and there is a 404 error.

如果图像不存在并且出现 404 错误,我会尝试用默认图像替换图像。

I would normally use the onerror method in the img tag but that doesn't seem to be working.

我通常会在 img 标签中使用 onerror 方法,但这似乎不起作用。

I am not sure how to do this with react.

我不知道如何通过反应来做到这一点。

Here is my component:

这是我的组件:

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;

采纳答案by emil

Since there is no perfect answer, I am posting the snippet I use. I am using reusable Imagecomponent that fallbacks to fallbackSrc.

由于没有完美的答案,我发布了我使用的代码段。我正在使用Image回退到fallbackSrc.

Since the fallback image could fail again and trigger infinite loop of re-rendering, I added erroredstate.

由于后备图像可能会再次失败并触发重新渲染的无限循环,因此我添加了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,
};

回答by Deepak Mallah

This works best for me

这对我最有效

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

回答by K.Arthur

You can use uncontrolled component:

您可以使用不受控制的组件:

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

回答by Skay

You need just define onError handler than change the state which will trigger component render method and eventually component will re-render with placeholder.

您只需要定义 onError 处理程序而不是更改将触发组件渲染方法并最终组件将使用占位符重新渲染的状态。

Please, don't use jQuery and React together!

请不要同时使用 jQuery 和 React!

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;

回答by Nitesh Ranjan

Arthur's answer will result in infinite callbacks if fallback image also fails.

如果后备图像也失败,亚瑟的回答将导致无限回调。

To avoid that, first set a state in the constructor for imageLoadError as true :

为了避免这种情况,首先在构造函数中为 imageLoadError 设置一个状态为 true :

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

and then check for this state value in onErrorfunction to avoid infinite callbacks,

然后在onError函数中检查这个状态值以避免无限回调,

the code will look like this :-

代码将如下所示:-

<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';
        }
    }}
/>

回答by Georgii Oleinikov

@DepH's answer is nice, but it does produce and infinite loop if your error source also doesn't load. This helped me avoid the callback loop:

@DepH 的回答很好,但如果您的错误源也没有加载,它确实会产生无限循环。这帮助我避免了回调循环:

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

回答by Saurabh Chauhan

Ran into a similar problem and the best solution i could find was Georgii Oleinikov's answer. (Doesn't require making new imageLoadErrorstate as suggested by Nitesh Ranjanin his answer)

遇到了类似的问题,我能找到的最佳解决方案是Georgii Oleinikov的答案。(不需要imageLoadError按照Nitesh Ranjan在他的回答中的建议创建新状态)

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

e.target.onerror = nullis not needed (and doesn't really help) because the if condition is enough to prevent the infinite loop(if backup image fails to load as well).

e.target.onerror = null不需要(并且没有真正帮助),因为 if 条件足以防止无限循环(如果备份图像也无法加载)。

So:

所以:

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

EDIT: The other way around is to set a flag outside the return brackets and check for the flag in the if statement. Code should look something like this:

编辑:另一种方法是在返回括号外设置一个标志并检查 if 语句中的标志。代码应如下所示:

render(){
 let errorflag=true;
 return(
            <img alt='' src={imageUrl} 
                    onError={(e)=>{ if (errorflag){ errorflag=false; e.target.src=url; } }} />
            );
} 

回答by Kevin

I took @Skay's answer and created a reusable Image component. Posting in case it helps anyone:

我接受了@Skay 的回答并创建了一个可重用的 Image 组件。发布以防它对任何人有帮助:

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;

回答by Mrinmay

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
 }}
/>

this is what I'm currently using.

这是我目前正在使用的。

回答by Gustavo Garcia

For those like me who also wanted to change the styles of the element and/or change the img source, just do something like this:

对于像我一样想要更改元素样式和/或更改 img 源的人,只需执行以下操作:

<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
  }}
/>

Hope it helps!

希望能帮助到你!