在以下情况下了解不变性和虚拟 DOM

Understanding immutability and virtual DOM in below case

阅读 here 关于不变性的内容后,我试图了解 React 的工作原理。我试图借助以下 3 个组件来理解,但它没有意义。

const bla = {a: 1};
class Test extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      a: 1,
    };
    this.onClick = () => this.setState(prevState => ({
      a: prevState.a + 1
    }));
  }
  render() {
    console.log('Render default');
    return <div id="test" onClick = {
      this.onClick
    } > DOM Updating: {
      this.state.a
    } < /div>;
  }
}

class Test1 extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      a: 1,
    };
    this.onClick = () => this.setState(prevState => ({
      a: 1
    }));
  }
  render() {
    console.log('Render 1');
    return <div id="test1" onClick = {
      this.onClick
    } > DOM not updating: {
      this.state.a
    } < /div>;
  }
}

class Test2 extends React.Component {
  constructor(props) {
    super(props);
    this.state = bla;
    this.onClick = () => {
      const mutating = this.state;
      mutating.a = this.state.a + 1;
      this.setState(mutating);
    };
  }
  render() {
    console.log('Render 2');
    return <div id="test2" onClick = {
      this.onClick
    } > DOM updating with mutation: {
      this.state.a
    } < /div>;
  }
}
ReactDOM.render( < div > < Test / > < Test1 / > < Test2 / > < /div>, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

如果我检查 div id="test1" 它会在每次点击时在 Chrome 开发工具中更新。想了解以下几点:

  1. 在单击期间如果我检查 div id="text1" 为什么这没有反映在开发工具中?在这里,我在每次点击 ({a: 1}) 时分配新的状态对象。正如上面的 link 所说

In fact, React.js does not need to have knowledge about what exactly changed. All it needs to know is whether the state changed at all or not.

  1. 在 Test2 组件中,我正在改变状态,但是为什么 dom 在点击时更新?
  2. updating nested state 的情况下,因为我们正在更新父级状态,这是否意味着 React 会认为所有其他子级已经更改了它们的值,并且即使它们没有更改也会重新渲染所有这些值?

1.) 在控制台输出中,您只会看到 Render 1,因为您使用静态值 1 调用了 setState。但实际上,每次您通过单击调用 setState 时,React 都会为组件设置一个新的(在新的 object 引用的意义上)状态,并触发一个新的渲染周期。

setState() will always lead to a re-render unless shouldComponentUpdate() returns false. Link

2.) 请参阅答案 1。此外,您还有一个 DOM 更改,因为 state changes are merged.

When you call setState(), React merges the object you provide into the current state.

在您的 Test2 单击处理程序代码中,变异将合并到当前状态。它是相同的 object,但重要的是,它的所有属性(此处 a 属性)将传播到状态中,从而产生一个新状态 object。

const mutating = this.state;
mutating.a = this.state.a + 1;
this.setState(mutating);

3.) 假设您有一个包含所有 child 组件的 Parent 组件。如果你改变 Parentpropsstate,所有 children 都会被 React 重新渲染,除非他们的 shouldComponentUpdate hook returns false 或者他们是 PureComponents,其 props 或 state 没有改变。

setState() enqueues changes to the component state and tells React that this component and its children need to be re-rendered with the updated state. Link

Rerender 意味着,对于每个 child,React 在 Reconciliation step. It only leads to a DOM update, if the child has really changed, otherwise nothing happens. See here 中比较以前和当前的版本以获得漂亮的可视化效果。