我正在为图像构建一个延迟加载组件。但我设置状态有问题。我收到只能更新已安装或正在安装的组件错误,但我在setState
内使用componentDidMount
,这样可以避免此类错误。
这是我的代码:
export default class Images extends React.Component {
constructor(props) {
super(props);
this.element = null;
this.state = {
loaded: false,
height: 0
};
}
componentDidMount() {
this.element = findDOMNode(this);
this.loadImage();
}
getDimensions() {
const w = this.element.offsetWidth;
let initw = 0;
let inith = 0;
let result;
const img = new Image();
img.src = this.props.url;
img.onload = (e) => {
initw = e.path[0].width;
inith = e.path[0].height;
result = (w / initw) * inith;
setTimeout(() => {
this.setState({
loaded: true,
height: `${result}px`
});
});
}
}
loadImage() {
_scrolling.add([this.element], () => {
if (this.element.classList.contains(_scrolling.classes.coming)) { // the image is visible
this.getDimensions();
}
});
}
render() {
const classes = this.state.loaded ? `${this.props.parentClass}__image--loaded` : null;
const styles = this.state.loaded ? {
maxHeight: this.state.height, minHeight: this.state.height, overflow: 'hidden'
} : null;
return (
<div className={`${this.props.parentClass}__image ${classes}`} style={styles}>
{this.state.loaded ?
<img
className={`${this.props.parentClass}__img`}
src={this.props.url}
title={this.props.title}
alt={this.props.title}
/>
: null
}
</div>
)
}
我相信问题在于img.onload
,但我不知道如何实现这一目标。我该怎么办?
答案 0 :(得分:4)
如果您尝试在未安装的组件上设置状态,则会出现类似的错误。有两种解决方案:
确保组件已安装:在检查组件是否已安装后使用DECLARE
v_counter int := 0 ;
select count(*) into v_counter from (
cursor get_sth is select * from table1 where condit..) ;
BEGIN
DBMS_OUTPUT.PUT_LINE (v_counter);
END ;
/
。
中止请求:当组件卸载时,我们可以抛弃请求,以便永远不会调用回调。为此,我们将利用另一个React生命周期钩子setstate();
。
答案 1 :(得分:2)
似乎在未安装的img.onload
组件实例上调用Images
处理程序。
图像加载是异步的,需要一些时间。当它最终完成并调用img.onload
处理程序时,无法保证您的组件仍然被挂载。
您必须使用componentWillUnmount
并确保:
有关检查组件是否已装入的更多信息:https://facebook.github.io/react/blog/2015/12/16/ismounted-antipattern.html
export default class Images extends React.Component {
constructor(props) {
super(props);
this.element = null;
this.state = {
loaded: false,
height: 0
};
this.images = []; // We’ll store references to the Image objects here.
}
componentDidMount() {
this.element = findDOMNode(this);
this.loadImage();
}
componentWillUnmount() {
this.images.forEach(img => img.src = ''); // Cancel the loading of images.
}
getDimensions() {
const w = this.element.offsetWidth;
let initw = 0;
let inith = 0;
let result;
const img = new Image();
img.src = this.props.url;
img.onload = (e) => {
initw = e.path[0].width;
inith = e.path[0].height;
result = (w / initw) * inith;
setTimeout(() => {
this.setState({
loaded: true,
height: `${result}px`
});
});
}
this.images.push(img); // Store the reference.
}
loadImage() {
_scrolling.add([this.element], () => {
if (this.element.classList.contains(_scrolling.classes.coming)) { // the image is visible
this.getDimensions();
}
});
}
render() {
const classes = this.state.loaded ? `${this.props.parentClass}__image--loaded` : null;
const styles = this.state.loaded ? {
maxHeight: this.state.height, minHeight: this.state.height, overflow: 'hidden'
} : null;
return (
<div className={`${this.props.parentClass}__image ${classes}`} style={styles}>
{this.state.loaded ?
<img
className={`${this.props.parentClass}__img`}
src={this.props.url}
title={this.props.title}
alt={this.props.title}
/>
: null
}
</div>
)
}
}