0

在阅读了关于不变性的here之后,我试图了解反应是如何工作的。我试图在以下 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}) 时都在状态下分配新对象。正如上面的链接所说

事实上,React.js 不需要知道到底发生了什么变化。它只需要知道状态是否发生了变化。

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

1 回答 1

1

1.) 在控制台输出中,您只需看到,因为您使用静态值Render 1调用。但实际上,每次单击调用时,React 都会为组件设置一个新的(在新对象引用的情况下)状态,并触发一个新的渲染周期。setState1setState

除非 shouldComponentUpdate() 返回 false,否则 setState() 将始终导致重新渲染。关联

2.)请参阅答案 1。此外,您有一个 DOM 更改,因为状态更改是合并的

当你调用 setState() 时,React 会将你提供的对象合并到当前状态。

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

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

3.) 假设您有一个Parent包含所有子组件的组件。如果你改变propsor stateof Parent,所有的孩子都会被 React 重新渲染,除非他们的shouldComponentUpdate钩子返回 false 或者他们是PureComponents,他们的 props 或 state 没有改变。

setState() 将组件状态的更改排入队列,并告诉 React 该组件及其子组件需要使用更新的状态重新渲染。关联

重新渲染意味着,对于每个孩子,React 在Reconciliation步骤中比较以前的版本和当前版本。如果孩子真的改变了,它只会导致 DOM 更新,否则什么也不会发生。请参阅此处以获得漂亮的可视化效果。

于 2019-09-05T09:59:15.960 回答