Javascript 事件侦听器后反应组件渲染

Javascript 事件侦听器后反应组件渲染,javascript,reactjs,jsx,render,lifecycle,Javascript,Reactjs,Jsx,Render,Lifecycle,我在让组件生命周期与React中的事件侦听器协作时遇到一些问题。下面是一个示例应用程序,它显示来自用户提供的URL的图像,并使用图像的宽度应用样式-在这种情况下,我希望图像以1/2的比例显示,以便获得图像的宽度,然后将其宽度设为实际宽度的1/2 为此,我使用图像的naturalWidth作为render()方法中的属性。我在componentDidMount()方法中创建了一个映像实例,然后使用事件侦听器等待映像加载以获得其宽度。如果没有事件侦听器,它将尝试在加载图像之前获取宽度,并且不会返回值

我在让组件生命周期与React中的事件侦听器协作时遇到一些问题。下面是一个示例应用程序,它显示来自用户提供的URL的图像,并使用图像的宽度应用样式-在这种情况下,我希望图像以1/2的比例显示,以便获得图像的宽度,然后将其宽度设为实际宽度的1/2

为此,我使用图像的
naturalWidth
作为
render()
方法中的属性。我在componentDidMount()方法中创建了一个映像实例,然后使用事件侦听器等待映像加载以获得其宽度。如果没有事件侦听器,它将尝试在加载图像之前获取宽度,并且不会返回值,因此侦听器确保在获得宽度之前加载图像。这就是我遇到问题的地方:
render()
方法不受事件侦听器的限制,因此即使在
render()
之前触发了
componentDidMount()
,它也总是以初始状态进行渲染。我希望通过将状态更改为事件的一部分,组件将重新渲染,但事实并非如此

在事件侦听器获取完图像宽度值后,确保内容呈现的“正确”方法是什么?

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
从'React'导入React,{Component,}
导入“./app.css”
类应用程序扩展组件{
//使用占位符图像设置初始状态
状态={
src:“https://cdn.jpegmini.com/user/images/slider_puffin_jpegmini_mobile.jpg",
宽度:“,
}
//获取组件安装时图像的宽度
componentDidMount(){
设Img=document.createElement(“Img”);
Img.src=this.state.src
Img.addEventListener(“加载”,()=>{
this.state.width=Img.naturalWidth
});
}
//图像更改时重新计算宽度(同上)
componentDidUpdate(){
设Img=document.createElement(“Img”);
Img.src=this.state.src
Img.addEventListener(“加载”,()=>{
this.state.width=Img.naturalWidth
});
}
//此函数用于在更改输入时更新状态
变化=(e)=>{
这是我的国家({
[e.target.name]:e.target.value
})
};
render(){
返回(
这个。更改(e)}
禁用={false}
>
)
}
}
导出默认应用程序

您可以有条件地渲染图像,并且仅当
this.state.width
包含一个值时才显示它

另外,您应该使用
setState
,而不是改变现有状态(这不是React方式,也不会导致状态更新)

与其重复两次图像宽度计算,不如将其放入函数中并调用该函数两次。也不要使用
而是尽可能使用

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(){
返回(
这个。更改(e)}
禁用={false}
>
{
this.state.width===''
无效的
: 
}
);
}

您可以有条件地渲染图像,并且仅当
this.state.width
包含一个值时才显示它

另外,您应该使用
setState
,而不是改变现有状态(这不是React方式,也不会导致状态更新)

与其重复两次图像宽度计算,不如将其放入函数中并调用该函数两次。也不要使用
而是尽可能使用

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(){
返回(
这个。更改(e)}
禁用={false}
>
{
this.state.width===''
无效的
: 
}
);
}

啊,那好多了。而且它有效!我唯一需要添加的是在“componentDidMount()”中添加一个条件语句,这样它就不会在设置状态后无限循环。非常感谢。啊,那好多了。而且它有效!我唯一需要添加的是在“componentDidMount()”中添加一个条件语句,这样它就不会在设置状态后无限循环。非常感谢。