我是javascript和React新手,所以我对React概念的思考仍然有些困惑。
我试图在React中创建简单的对象检查器。
这是属性行元素:
class PropertyRow extends React.Component {
constructor(props) {
super(props);
this.state = {
propertyName: this.props.propertyName,
propertyValue: this.props.propertyValue
};
alert(this.props.propertyName + " evoked in constructor");
}
render() {
return (
<div>{this.props.propertyName} = {this.props.propertyValue}</div>
// <div>{this.state.propertyName} = {this.state.propertyValue}</div>
);
}
}
在此,我试图在组件PropertyRows中动态读取对象的所有属性。
class PropertyRows extends React.Component {
constructor(props) {
super(props);
this.createProRows = this.createProRows.bind(this);
}
createProRows(obj) {
const propArr = [];
for (const key of Object.keys(obj)) {
const val = obj[key];
propArr.push(<PropertyRow propertyName={key} propertyValue={val} />);
}
return propArr;
}
render() {
return <div>{this.createProRows(this.props.obj)}</div>;
}
}
在这里,我测试了这个很棒的代码
class Express extends React.Component {
constructor(props) {
super(props);
this.state = {
soldiers: 0,
captain:'John Maverick'
};
this.doClick = this.doClick.bind(this);
}
doClick() {
const obj = {
soldiers: this.state.soldiers + 1,
country:'Australia' //add new property
};
this.setState(obj);
}
render() {
return (
<div onClick={this.doClick}>
<PropertyRows obj={this.state} />
</div>
);
}
}
ReactDOM.render(<Express />, document.getElementById("root"));
单击文本时,将看到“士兵”属性增加一。代码是错误的,我不知道为什么,或者也许我这样做,但是我绝对不知道如何在React metaanguage中解决它。
<PropertyRow propertyName={key} propertyValue={val}/>
数组将是浏览对象属性的好方法。但是看起来,呈现的HTML DOM对象没有被销毁和重新创建。当要表达doClick
函数中的新对象时,它们神秘地重新连接。 此外
在doClick
中创建另一个对象时,属性obj.captain
仍然存在(在浏览器窗口中),这可能是因为基础HTML DOM元素没有被破坏。添加新属性country: 'Australia'
似乎可以。
当我第二次期望调用<PropertyRow propertyName={key} propertyValue={val}/>
时,该构造函数将被触发,因为它是在新数组中创建并推送的。但事实并非如此。仅针对新属性country: 'Australia'
似乎,我必须以某种方式销毁渲染的HTML DOM元素,以强制做出反应来重新创建它们。但是如何? 还是有另一种方法?
我对这篇冗长的文字深表歉意。我希望阅读起来不会那么复杂。
感谢
答案 0 :(得分:0)
delete obj.captain
不执行任何操作,因为captain
中没有obj
键。 captain
中存在this.state
键,不建议将其删除,因为React状态通常是不可变的。
将this.state
与this.setState
一起使用可能会导致争用情况,应改用state updater函数。
应该是:
doClick() {
this.setState(state => ({
soldiers: state.soldiers + 1,
country:'Australia',
captain: undefined
}));
}
PropertyRow
的问题在于它在构造函数中只处理道具一次。 PropertyRow
构造函数仅被触发一次,因为该组件已经被挂载,现在仅在新的道具上更新(这是React生命周期挂钩的illustrative diagram)。
如果状态应该从接收到的道具派生,则应使用getDerivedStateFromProps
hook,它会在初始渲染和下一次更新之前从道具映射状态。在这种情况下,不需要状态,因为状态属性和道具没有区别。足够了:
class PropertyRow extends React.Component {
render() {
return (
<div>{this.props.propertyName} = {this.props.propertyValue}</div>
);
}
}
PropertyRow
可以重写为功能组件,因为它不能从类中受益。