react类组件和函数组件的执行更新区别

298 阅读2分钟

单独改变prop不会触发更新

类组件

import React from "react";
import "./styles.css";

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.b = { bb: 0 };
  }
  render() {
    return (
      <div className="App">
        <ContentB val={this.b} />
        <button
          onClick={() => {
            console.log(this.b);
            this.b.bb++;
          }}
        >
          add
        </button>
      </div>
    );
  }
}

class ContentB extends React.Component {
  constructor(props) {
    super(props);
  }
  componentWillReceiveProps() {
    console.log("ContentB ReceiveProps");
  }
  componentDidUpdate() {
    console.log("ContentB Update");
  }
  render() {
    return <h1>{this.props.val.bb}</h1>;
  }
}

函数组件相同

import React from "react";
import "./styles.css";

export default function App() {
  let b = {bb: 0}
  render() {
    return (
      <div className="App">
        <ContentB val={b} />
        <button
          onClick={() => {
            console.log(this.b);
            b.bb++;
          }}
        >
          add
        </button>
      </div>
    );
  }
}

function ContentB(props) {
  componentWillReceiveProps() {
    console.log("ContentB ReceiveProps");
  }
  componentDidUpdate() {
    console.log("ContentB Update");
  }
  render() {
    return <h1>{this.props.val.bb}</h1>;
  }
}

state改变触发更新

类组件

import React from "react";
import "./styles.css";

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      a: 0
    };
    this.b = { bb: 0 };
  }
  render() {
    return (
      <div className="App">
        <Content val={this.state.a} />
        <ContentB val={this.b} />
        <button
          onClick={() => {
            console.log(this.state.a, this.b);
            this.b.bb++;
            // this.setState(pre => {
            //   return { a: pre.a + 1 };
            // });
          }}
        >
          add
        </button>
      </div>
    );
  }
}

class Content extends React.Component {
  constructor(props) {
    super(props);
  }
  componentWillReceiveProps() {
    console.log("Content ReceiveProps");
  }
  componentDidUpdate() {
    console.log("Content Update");
  }
  render() {
    return <h1>{this.props.val}</h1>;
  }
}

class ContentB extends React.Component {
  constructor(props) {
    super(props);
  }
  componentWillReceiveProps() {
    console.log("ContentB ReceiveProps");
  }
  componentDidUpdate() {
    console.log("ContentB Update");
  }
  render() {
    return <h1>{this.props.val.bb}</h1>;
  }
}


组件此时不更新
import React from "react";
import "./styles.css";

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      a: 0
    };
    this.b = { bb: 0 };
  }
  render() {
    return (
      <div className="App">
        <Content val={this.state.a} />
        <ContentB val={this.b} />
        <button
          onClick={() => {
            console.log(this.state.a, this.b);
            this.b.bb++;
            // this.setState(pre => {
            //   return { a: pre.a + 1 };
            // });
          }}
        >
          add
        </button>
      </div>
    );
  }
}

class Content extends React.Component {
  constructor(props) {
    super(props);
  }
  componentWillReceiveProps() {
    console.log("Content ReceiveProps");
  }
  componentDidUpdate() {
    console.log("Content Update");
  }
  render() {
    return <h1>{this.props.val}</h1>;
  }
}

class ContentB extends React.Component {
  constructor(props) {
    super(props);
  }
  componentWillReceiveProps() {
    console.log("ContentB ReceiveProps");
  }
  componentDidUpdate() {
    console.log("ContentB Update");
  }
  render() {
    return <h1>{this.props.val.bb}</h1>;
  }
}

此时组件更新
!注意,此时ContentB也会改变,说明react是挂载时new出一个对象,然后每次调用这个对象的render() {}来update组件
import React, { useState } from "react";
import "./styles.css";

export default function App() {
  const [a, setA] = useState(0);
  let b = { bb: 0 };
  return (
    <div className="App">
      <Content val={a} />
      <ContentB val={b} />
      <button
        onClick={() => {
          console.log(a, this.b);
          b.bb++;
          setA(pre => pre + 1);
        }}
      >
        add
      </button>
    </div>
  );
}

function Content(props) {
  return <h1>{props.val}</h1>;
}

function ContentB(props) {
  return <h1>{props.val.bb}</h1>;
}
此时组件更新
!注意,此时ContentB并没有更改!和类组件不一样的是,stete被存到了别处,似乎是get,set调用的,
每次state更新都重新调用一次函数,用返回的结果来更新组件。
正是因为重新调用函数,新建了作用域,新的作用域中let b = { bb: 0 },只能访问到b.bb的默认值