在事件侦听器之后反应组件渲染
React component render after event listener
我在获取组件生命周期以与 React 中的事件侦听器协作时遇到了一些问题。下面是一个示例应用程序,它显示来自用户提供的 URL 的图像,并使用图像的宽度来应用样式——在这种情况下,我希望图像以 1/2 的比例显示,所以我得到了宽度图像的宽度,然后将其宽度设为实际宽度的 1/2。
为此,我在 render()
方法中使用图像的 naturalWidth
作为 属性。我在 componentDidMount() 方法中创建了一个图像实例,然后使用事件侦听器等待图像加载完毕以获取其宽度。如果没有事件侦听器,它将尝试在加载图像之前获取宽度并且不会 return 一个值,因此侦听器确保在我们获取宽度之前加载图像。这就是我 运行 遇到问题的地方:render()
方法不受事件侦听器的限制,因此即使 在 之前触发了 componentDidMount()
render()
,它始终以初始状态呈现。我希望通过更改状态作为事件的一部分,组件将重新呈现,但事实并非如此。
确保在事件侦听器完成获取图像宽度值后呈现内容的“正确”方法是什么?
import React, {Component,} from 'react'
import './app.css'
class App extends Component {
// setting the initial state with a placeholder image
state = {
src: "https://cdn.jpegmini.com/user/images/slider_puffin_jpegmini_mobile.jpg",
width: "",
}
// Getting the width of the image when the component mounts
componentDidMount() {
let Img = document.createElement("img");
Img.src = this.state.src
Img.addEventListener("load", () => {
this.state.width = Img.naturalWidth
});
}
//re-calculating the width when the image changes (exact same as above)
componentDidUpdate() {
let Img = document.createElement("img");
Img.src = this.state.src
Img.addEventListener("load", () => {
this.state.width = Img.naturalWidth
});
}
// This function updates the state when the input is changed
change = (e) => {
this.setState({
[e.target.name]: e.target.value
})
};
render() {
return (
<div className="app">
<input
name="src"
value={this.state.src}
onChange={e => this.change(e)}
disabled={false}
></input>
<img
src={this.state.src}
style={{width: this.state.width / 2}}
></img>
</div>
)
}
}
export default App
您可以有条件地渲染图像,并且仅在 this.state.width
包含一个值时才显示它。
此外,您应该使用 setState
,而不是改变现有状态(这不是 React 的处理方式,不会导致状态更新)。
与其重复两次图像宽度计算,不如将其放入一个函数中并调用该函数两次。尽可能 remember to use const
而不是 let
。
calcImageWidth() {
const img = document.createElement("img");
img.src = this.state.src
img.addEventListener("load", () => {
// use this technique in componentDidUpdate too
this.setState(prevState => ({ ...prevState, width: img.naturalWidth }));
});
}
componentDidMount() {
this.calcImageWidth();
}
componentDidUpdate() {
this.calcImageWidth();
}
render() {
return (
<div className="app">
<input
name="src"
value={this.state.src}
onChange={e => this.change(e)}
disabled={false}
></input>
{
this.state.width === ''
? null
: <img
src={this.state.src}
style={{ width: this.state.width / 2 }}
></img>
}
</div>
);
}
我在获取组件生命周期以与 React 中的事件侦听器协作时遇到了一些问题。下面是一个示例应用程序,它显示来自用户提供的 URL 的图像,并使用图像的宽度来应用样式——在这种情况下,我希望图像以 1/2 的比例显示,所以我得到了宽度图像的宽度,然后将其宽度设为实际宽度的 1/2。
为此,我在 render()
方法中使用图像的 naturalWidth
作为 属性。我在 componentDidMount() 方法中创建了一个图像实例,然后使用事件侦听器等待图像加载完毕以获取其宽度。如果没有事件侦听器,它将尝试在加载图像之前获取宽度并且不会 return 一个值,因此侦听器确保在我们获取宽度之前加载图像。这就是我 运行 遇到问题的地方:render()
方法不受事件侦听器的限制,因此即使 在 之前触发了 componentDidMount()
render()
,它始终以初始状态呈现。我希望通过更改状态作为事件的一部分,组件将重新呈现,但事实并非如此。
确保在事件侦听器完成获取图像宽度值后呈现内容的“正确”方法是什么?
import React, {Component,} from 'react'
import './app.css'
class App extends Component {
// setting the initial state with a placeholder image
state = {
src: "https://cdn.jpegmini.com/user/images/slider_puffin_jpegmini_mobile.jpg",
width: "",
}
// Getting the width of the image when the component mounts
componentDidMount() {
let Img = document.createElement("img");
Img.src = this.state.src
Img.addEventListener("load", () => {
this.state.width = Img.naturalWidth
});
}
//re-calculating the width when the image changes (exact same as above)
componentDidUpdate() {
let Img = document.createElement("img");
Img.src = this.state.src
Img.addEventListener("load", () => {
this.state.width = Img.naturalWidth
});
}
// This function updates the state when the input is changed
change = (e) => {
this.setState({
[e.target.name]: e.target.value
})
};
render() {
return (
<div className="app">
<input
name="src"
value={this.state.src}
onChange={e => this.change(e)}
disabled={false}
></input>
<img
src={this.state.src}
style={{width: this.state.width / 2}}
></img>
</div>
)
}
}
export default App
您可以有条件地渲染图像,并且仅在 this.state.width
包含一个值时才显示它。
此外,您应该使用 setState
,而不是改变现有状态(这不是 React 的处理方式,不会导致状态更新)。
与其重复两次图像宽度计算,不如将其放入一个函数中并调用该函数两次。尽可能 remember to use const
而不是 let
。
calcImageWidth() {
const img = document.createElement("img");
img.src = this.state.src
img.addEventListener("load", () => {
// use this technique in componentDidUpdate too
this.setState(prevState => ({ ...prevState, width: img.naturalWidth }));
});
}
componentDidMount() {
this.calcImageWidth();
}
componentDidUpdate() {
this.calcImageWidth();
}
render() {
return (
<div className="app">
<input
name="src"
value={this.state.src}
onChange={e => this.change(e)}
disabled={false}
></input>
{
this.state.width === ''
? null
: <img
src={this.state.src}
style={{ width: this.state.width / 2 }}
></img>
}
</div>
);
}