首页 > 解决方案 > 在 React 中制作简单的对象检查器的几个问题

问题描述

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

  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'

看来,我必须以某种方式破坏呈现的 HTML DOM 元素才能强制做出反应以重新创建它们。但是怎么做?还是有其他方法?

对于这么长的文字,我深表歉意。我希望它不是那么复杂的阅读。

谢谢

标签: javascriptreactjs

解决方案


delete obj.captain什么都不做,captain因为obj. captainkey 存在于 中this.state,并且不鼓励从中删除它,因为 React 状态通常是不可变的。

this.state与 with 一起使用可能this.setState会导致竞态条件,应使用状态更新函数。

它应该是:

  doClick() {
    this.setState(state => ({
      soldiers: state.soldiers + 1,
      country:'Australia',
      captain: undefined  
    }));
  }

问题PropertyRow在于它在构造函数中处理一次道具。PropertyRow构造函数只被触发一次,因为组件已经被挂载,现在它只在新的道具上更新(这里是 React 生命周期钩子的示意图)。

如果一个状态应该从收到的 props 派生,则应该使用getDerivedStateFromPropshook,它在初始渲染和下一次更新之前从 props 映射一个状态。在这种情况下,不需要状态,因为状态属性和道具没有区别。拥有以下就足够了:

class PropertyRow extends React.Component {
  render() {
    return (
      <div>{this.props.propertyName} = {this.props.propertyValue}</div>
    );
  }
}

并且PropertyRow可以重写为功能组件,因为它不能从类中受益。


推荐阅读