react.js Replace img src onerror
我有一个React组件,它是列表中的详细信息视图。
我试图用默认图像替换该图像,如果该图像不存在并且出现404错误。
我通常会在img标签中使用onerror方法,但这似乎不起作用。
我不确定如何做出反应。
这是我的组件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | 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 ( <h4>{this.state.contact.displayname}</h4> <img src={this.state.imageUrl} /> ); } } export default Contact; |
这对我来说最好
1 | <img src={record.picture} onError={(e)=>{e.target.onerror = null; e.target.src="image_path_here"}}/> |
您可以使用不受控制的组件:
1 2 3 | <img src={this.state.img} ref={img => this.img = img} onError={ () => this.img.src = 'img/default.img' }> |
您只需要定义onError处理程序,而不是更改状态即可,该状态将触发组件的渲染方法,最终组件将使用占位符重新渲染。
请不要将jQuery和React一起使用!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | 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 ( <h4>{this.state.contact.displayname}</h4> <img onError={this.onError.bind(this)} src={this.state.imageUrl} /> ); } export default Contact; |
由于没有完美的答案,因此我发布了我使用的代码段。我正在使用回退到
由于后备图像可能再次失败并触发重新渲染的无限循环,因此我添加了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | 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, }; |
如果后备图像也失败,Arthur的答案将导致无限回调。
为了避免这种情况,请首先在构造函数中将imageLoadError的状态设置为true:
1 2 3 4 5 6 | constructor(props) { super(props); this.state = { imageLoadError: true, }; } |
然后在
该代码将如下所示:-
1 2 3 4 5 6 7 8 9 10 11 | <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'; } }} /> |
遇到类似的问题,我能找到的最佳解决方案是Georgii Oleinikov的答案。 (不需要像Nitesh Ranjan在回答中所建议的那样建立新的
1 2 3 4 5 | onError={(e)=>{ if (e.target.src !=="image_path_here"){ e.target.onerror = null; e.target.src="image_path_here";} } } |
不需要
所以:
1 2 3 4 | onError={(e)=>{ if (e.target.src !=="image_path_here"){ e.target.src="image_path_here";} } } |
编辑:另一种方法是在返回括号外设置一个标志,并在if语句中检查该标志。代码应如下所示:
1 2 3 4 5 6 7 | render(){ let errorflag=true; return( <img alt='' src={imageUrl} onError={(e)=>{ if (errorflag){ errorflag=false; e.target.src=url; } }} /> ); } |
@DepH的答案很好,但是如果您的错误源也没有加载,它的确会产生无限循环。这帮助我避免了回调循环:
1 2 | onError={(e)=>{ if (e.target.src !=="image_path_here") { e.target.onerror = null; e.target.src="image_path_here"; } }} |
我接受了@Skay的回答,并创建了一个可重用的Image组件。张贴以防万一:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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; |
1 2 3 4 5 6 7 8 9 10 11 | 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 }} /> |
这就是我目前正在使用的。
这是使用钩子的答案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | 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} /> } |
如果要处理
https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html#recommendation-fully-uncontrol-component-with-a-key
1 | <Image key='someUrl' src='someUrl' fallback='fallbackUrl' alt='...' /> |
使用此类键可能失败的唯一极端人为边缘情况是兄弟组件。我认为,只有一个同级节点具有相同的密钥才能渲染。为了解决这个问题,您可以将Image包装在
1 2 | <><Image key={srcProp} ... /></> <><Image key={srcProp} ... /></> |
对于像我这样也想更改元素样式和/或更改img源的人,只需执行以下操作:
1 2 3 4 5 6 7 8 | <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 }} /> |
希望能帮助到你!
如果有人将图像src与require一起使用,则onError不能用作-
1 | <img src={require(`./../../assets/images/${props.imgName}.png`)} className="card-img" alt={props.name} /> |
然后require引发错误,在这里我尝试了多种方法,然后尝试捕获块解决方案,例如-
1 2 3 4 5 6 | let imgSrc; try { imgSrc = require(`./../../assets/images/${props.imgName}.png`); } catch { imgSrc = require(`./../../assets/images/default.png`); } |
并用作
1 | <img src={imgSrc} className="card-img" alt={props.name} /> |
如果可以的话,可以使用
1 2 3 | <object data={expected_image} type="image/jpg"> <img src={DEFAULT} alt="404" /> </object> |
查看此答案以获取更多详细信息
https://stackoverflow.com/a/29111371/1334182
那就是我做到的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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}/>; } } |
我这样写。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | 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 ( <NoImageSVG width='5rem' height='5rem' /> ); } return <img src={src} alt={alt} className={className} onError={onError} />; }; export default React.memo(ImgWithFallback, () => true); |
这对我有用。
1 2 3 | {<img className="images" src={`/images/${student.src ? student.src :"noimage.png" }`} alt= {student.firstname} />} |
学生是我的数组的名称,当没有图像显示时,noimage是图像。