我是新来的反应者,我不明白为什么h1标签中的 title 会被更新,但是Image组件中的 url 没有?
import React, { useState, useEffect, useContext } from 'react';
import Image from './Image';
import Size from '../index';
export default function Listing(props) {
const [title, setTitle] = useState(props.title);
const [url, setUrl] = useState(props.url);
const value = useContext(Size);
return (
<div>
<Image url={url} size={value.size} />
<h1>{title}</h1>
<form>
<input id='URL' type='text' />
<button
onClick={e => {
e.preventDefault();
setUrl(document.getElementById('URL').value);
setTitle(document.getElementById('URL').value);
}}
>
Submit
</button>
</form>
</div>
);
}
到目前为止,我的猜测是如果道具发生变化,React不会更新子组件,但是那我该如何手动对其进行更新?
import React from 'react';
export default class Image extends React.Component {
//console.log(props.size);
constructor(props) {
super(props);
this.url = props.url;
this.size = props.size;
}
render() {
return <img src={this.url} style={{ height: this.size + 'px' }} alt='' />;
}
}```
答案 0 :(得分:4)
您无需将props值分配给子组件中的class变量。由于您是在构造函数中执行此操作,因此不会更新。
更改您的图片组件以直接使用道具中的数据
import React from 'react';
export default class Image extends React.Component {
//console.log(props.size);
constructor(props) {
super(props);
}
render() {
return <img src={this.props.url} style={{ height: this.props.size + 'px' }} alt='' />;
}
}
答案 1 :(得分:3)
您的代码有很多“气味”。这是简短的快速解答:
将此:src={this.url}
更改为:src={this.props.url}
。
图像从未更新的原因是因为:
constructor(props) {
super(props);
this.url = props.url;
this.size = props.size;
}
您正在将局部变量设置为初始prop值。由于您是在 constructor 中进行设置的,因此这些行只会在创建组件时执行,而永远不会在发送新的prop时执行。React仍会触发重新渲染,因为您正在发送新的道具,但从未使用新的值,因此保留了旧的结果。
答案略长:
像在这里一样直接混合从DOM读取的值并不是一个好主意:
setUrl(document.getElementById('URL').value);
setTitle(document.getElementById('URL').value);
相反,有2个状态。一个保存了输入的当前值,该值随每次击键而更新,另一个保存了发送到Image组件的值。
也许像这样:
export default function Listing(props) {
const [title, setTitle] = useState(props.title);
const [inputUrl, setInputUrl] = useState(props.url);
const [url, setUrl] = useState(props.url);
const value = useContext(Size);
return (
<div>
<Image url={url} size={value.size} />
<h1>{title}</h1>
<form>
<input
value={inputUrl}
onChange={e => setInputUrl(e.target.value)}
/>
<button
type="button"
onClick={() => {
setUrl(inputUrl);
setTitle(inputUrl);
}}
>
Submit
</button>
</form>
</div>
);
}
还请注意,由于默认类型为e.preventDefault()
,因此我删除了type="button"
并向您的按钮添加了submit
,这可能会刷新您的页面。
答案 2 :(得分:0)
您的图像组件无法正确处理道具。将prop值分配给类变量将不会按您期望的那样工作,因为该代码执行一次(因为它在构造函数内部)。
constructor(props) {
super(props);
// The following causes trouble.
this.url = props.url;
this.size = props.size;
}
您可以像下面这样在构造函数中分配一个状态,但这不能解决您的问题。您需要在某个地方相应地更新状态。有多种生命周期方法可供选择,相匹配的是:UNSAFE_componentWillReceiveProps
,但顾名思义,我将不再使用它。
constructor(props) {
super(props);
this.state = {
url = props.url,
size = props.size,
};
}
基本上,您可以通过将道具传递到JSX中并摆脱构造函数的内容来解决您的问题,因为您不需要根据输入值进行任何状态计算,因为这些值是url和大小。
import React from 'react';
export default class Image extends React.Component {
render() {
return <img src={this.props.url} style={{ height: this.props.size + 'px' }} alt='' />;
}
}