在React中制作简单的对象检查器的几个麻烦

时间:2019-02-14 22:20:21

标签: javascript reactjs

我是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中解决它。

  1. 我希望,动态创建的<PropertyRow propertyName={key} propertyValue={val}/>数组将是浏览对象属性的好方法。但是看起来,呈现的HTML DOM对象没有被销毁和重新创建。当要表达doClick函数中的新对象时,它们神秘地重新连接。

此外

  1. doClick中创建另一个对象时,属性obj.captain仍然存在(在浏览器窗口中),这可能是因为基础HTML DOM元素没有被破坏。添加新属性country: 'Australia'似乎可以。

  2. 当我第二次期望调用<PropertyRow propertyName={key} propertyValue={val}/>时,该构造函数将被触发,因为它是在新数组中创建并推送的。但事实并非如此。仅针对新属性country: 'Australia'

  3. 触发

似乎,我必须以某种方式销毁渲染的HTML DOM元素,以强制做出反应来重新创建它们。但是如何? 还是有另一种方法?

我对这篇冗长的文字深表歉意。我希望阅读起来不会那么复杂。

感谢

1 个答案:

答案 0 :(得分:0)

delete obj.captain不执行任何操作,因为captain中没有obj键。 captain中存在this.state键,不建议将其删除,因为React状态通常是不可变的。

this.statethis.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可以重写为功能组件,因为它不能从类中受益。