react.js替换img src onerror

Joe*_*ler 39 javascript http-status-code-404 reactjs

我有一个react组件,它是列表中的详细信息视图.

如果图像不存在并且存在404错误,我试图用默认图像替换图像.

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

我不知道如何做出反应.

这是我的组件:

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;
Run Code Online (Sandbox Code Playgroud)

Dee*_*lah 81

这对我来说效果最好

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

  • 似乎这个方法可能会导致无限回调,如果"image_path_here"产生和错误... (22认同)
  • @tomhughes,当“ image_path_here”失败时,它将阻止无限回调 (4认同)
  • @DeepakMallah我按照你的代码 `&lt;img src={imageUrl} className={cs.image} onError={(e) =&gt; {e.target.src = 'https://upload.wikimedia.org/wikipedia/en /c/c3/The_Martian_2014.jpg'; e.target.onError = null;}} /&gt;` 但是,Safari 中的控制台仍然显示错误“加载资源失败:服务器响应状态为 404(未找到)”。正常吗?如何消除此控制台错误?谢谢。 (4认同)

小智 13

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

<img src={this.state.img} ref={img => this.img = img} onError={
    () => this.img.src = 'img/default.img'
}>
Run Code Online (Sandbox Code Playgroud)


Ska*_*kay 9

您只需定义onError处理程序,而不是更改将触发组件呈现方法的状态,最终组件将使用占位符重新呈现.

请不要一起使用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;
Run Code Online (Sandbox Code Playgroud)

  • @GuilhermeNunes [React Bootstrap](https://react-bootstrap.github.io/) 没有! (3认同)

Mar*_*cos 8

2021 使用 React Functional Components、Hooks 和 TypeScript 更新答案

// ImageWithFallback.tsx
import React, { ImgHTMLAttributes, useState } from 'react'

interface Props extends ImgHTMLAttributes<any> {
  fallback: string
}

export default function ImageWithFallback({ fallback, src, ...props }: Props) {
  const [imgSrc, setImgSrc] = useState<string | undefined>(src)
  const onError = () => setImgSrc(fallback)

  return <img src={imgSrc ? imgSrc : fallback} onError={onError} {...props} />
}


Run Code Online (Sandbox Code Playgroud)


Geo*_*kov 7

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

onError={(e)=>{ if (e.target.src !== "image_path_here") 
    { e.target.onerror = null; e.target.src="image_path_here"; } }}
Run Code Online (Sandbox Code Playgroud)


小智 7

它如此简单

e.target.onerror = null 如果错误图片也无法加载jsx

<img 
   src={imageSrc}
   onError={(e) => (e.target.onerror = null, e.target.src = imageErrorSrc)}/>
Run Code Online (Sandbox Code Playgroud)

  • 如果 `imageErrorSrc` 是无效的 url,则 `onError` 会无限运行。为什么? (2认同)

emi*_*mil 6

由于没有完美的答案,因此我发布了我使用的代码段。我正在使用Image回退到的可重用组件fallbackSrc

由于后备图片可能再次失败并触发无限次重新渲染循环,因此我添加了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,
};
Run Code Online (Sandbox Code Playgroud)

  • 需要注意的是:如果您使用 React 进行服务器端渲染,则无法正常工作,因为图像是异步加载的,并且在进行水合作用时,所有错误都已被触发。 (5认同)

小智 5

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
 }}
/>
Run Code Online (Sandbox Code Playgroud)

这就是我目前正在使用的。


Nit*_*jan 5

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

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

constructor(props) {
    super(props);
    this.state = {
      imageLoadError: true,
    };
}
Run Code Online (Sandbox Code Playgroud)

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

该代码将如下所示:-

<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';
        }
    }}
/>
Run Code Online (Sandbox Code Playgroud)


Sau*_*han 5

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

onError={(e)=>{ if (e.target.src !== "image_path_here"){
                    e.target.onerror = null;
                     e.target.src="image_path_here";}
                }
           }
Run Code Online (Sandbox Code Playgroud)

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

所以:

onError={(e)=>{ if (e.target.src !== "image_path_here"){
                 e.target.src="image_path_here";}
               }
         }
Run Code Online (Sandbox Code Playgroud)

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

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


jtc*_*jtc 5

这是使用钩子的答案:

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} />
}
Run Code Online (Sandbox Code Playgroud)

如果你是要处理的src道具变化,可以传递key的道具srchttps://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='...' />
Run Code Online (Sandbox Code Playgroud)

使用这样的键可能会失败的唯一极端人为的边缘情况是使用同级组件。我认为如果它们具有相同的键,则只会呈现一个兄弟节点。为了解决这个问题,您可能可以将 Image 包装在<> Fragment.

<><Image key={srcProp} ... /></>
<><Image key={srcProp} ... /></>
Run Code Online (Sandbox Code Playgroud)