react的生命周期和使用

完整的生命周期
我们都知道生命周期分为三个大阶段:
- 挂载
- 更新
- 卸载
挂载的时候我们我们有 constructor 、 getDerivedStateFromProps 、render 、 componentDidMount (即将被废弃的生命周期不再写入,也不推荐大家继续使用)
挂载
constructor
它一般用于初始化state和绑定事件,只有在这里对state赋值直接赋值,而且最好不要在这里进行副作用的操作,后面会做解释。还有不要将props直接赋值给state
  constructor(props) {
    super(props);
    this.state = {
      name: this.props.name,
    };
  }
这种写法不会及时的更新状态
如下:
// 父组件
import React, {Component} from "react";
import Son from "./son";
class App extends Component {
  constructor() {
    this.state = {
      number: 0,
    };
  }
  render() {
    const {number} = this.state;
    return (
        <div>
          <button onClick={() => this.setState({number: number + 1})}>add</button>
          <br/>
          <Son name={this.state.number}/>
        </div>
    );
  }
}
export default App;
// 子组件
import React, {Component} from "react";
class Son extends Component {
  constructor(props) {
    super(props);
    this.state = {
      name: this.props.name,
    };
  }
  render() {
    return (
        <div>
          <p>将props赋值给了子组件state</p>
          {this.state.name}
          <br/>
          <p>直接使用了this.props.number</p>
          {this.props.name}
        </div>
    );
  }
}
export default Son;
父组件点击一次以后,子组件中直接使用 this.props.number  的更新了,而通过赋值给state的没有更新。

-------------------------------------------------------------------------------------------------------------------**
getDerivedStateFromProps
-------------------------------------------------------------------------------------------------------------------
render
此方法在挂载阶段肯定会被调用,而在更新阶段会取决于 UNSAFE_componentWillUpdate和shouldComponentUpdate()返回值影响
它应该返回以下类型之一
- React 元素。通常通过 JSX 创建。例如,
<div />会被 React 渲染为 DOM 节点,<MyComponent />会被 React 渲染为自定义组件,无论是<div />还是<MyComponent />均为 React 元素。- 数组或 fragments。 使得 render 方法可以返回多个元素。欲了解更多详细信息,请参阅 fragments 文档。
- Portals。可以渲染子节点到不同的 DOM 子树中。欲了解更多详细信息,请参阅有关 portals 的文档
- 字符串或数值类型。它们在 DOM 中会被渲染为文本节点
- 布尔类型或
null。什么都不渲染。(主要用于支持返回test && <Child />的模式,其中 test 为布尔类型。)
componentDidMount
会在组件挂载到dom上的时候立即调用,如果这个时候调用setState的话会再次触发render,但是会在屏幕更新出来之前完成渲染。下面示例:
import React, {Component} from "react";
class SonTwo extends Component {
  constructor(props) {
    super(props);
    this.state = {
      number: 0,
    };
  }
  componentDidMount() {
    this.setState({
      number: this.state.number + 1,
    });
  }
  render() {
    console.log("我执行了", this.state.number);
    return (
        <div>
          {this.state.number}
        </div>
    );
  }
}
export default SonTwo;

**这里为什么会出现4次,是因为 react的 **[**严格模式**](https://zh-hans.reactjs.org/docs/strict-mode.html#gatsby-focus-wrapper)
严格模式不能自动检测到你的副作用,但它可以帮助你发现它们,使它们更具确定性。通过故意重复调用以下函数来实现的该操作:
- class 组件的
constructor,render以及shouldComponentUpdate方法- class 组件的生命周期方法
getDerivedStateFromProps- 函数组件体
- 状态更新函数 (即
setState的第一个参数)- 函数组件通过使用
useState,useMemo或者useReducer
所以使用的时候需要注意如果出现循环更改可能会出现性能问题
更新
getDerivedStateFromProps
shouldComponentUpdate
每次props或者state变化是render之前它会被调用,默认是正常调用render,但是如果这个周期函数返回false就会停止组件的渲染,不过父组件的state或者props变化不引起本组件改变,其子组件的state改变依然会更新
// 父组件
import React, {Component} from "react";
import Son from "./son";
class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      number: 0,
    };
  }
  shouldComponentUpdate(nextProps, nextState, nextContext) {
    return nextState.number > 10;
  }
  render() {
    const {number} = this.state;
    return (
        <div style={{border: "1px solid red", margin: "6px"}}>
          <button onClick={() => this.setState({number: number + 1})}>add
          </button>
          <br/>
          <span>父组件中的number: </span>{this.state.number}
          <br/>
          <Son number={this.state.number}/>
          {/*<SonTwo/>*/}
        </div>
    );
  }
}
export default App;
// 子组件
import React, {Component} from "react";
class Son extends Component {
  constructor(props) {
    super(props);
    this.state = {
      number: 0,
    };
  }
  render() {
    return (
        <div style={{border: "1px solid blue", margin: "6px", padding: "20px"}}>
          <button onClick={() => {
            this.setState({
              number: this.state.number + 1,
            });
          }}>ADD
          </button>
          <br/>
          <br/>
          <span>父组件中的值: </span>{this.props.number}
          <br/>
          <span>子组件中的值: </span>{this.state.number}
        </div>
    );
  }
}
export default Son;
效果如图:
 
   
图1 是点击了外层的父节点的add后子节点并没接收到父节点传递过来的值,因为父节点的render并没有被触发。
图2 是点击了内层的子节点上ADD后发现子组件触发了render
-------------------------------------------------------------------------------------------------------------------**
render
同上
-------------------------------------------------------------------------------------------------------------------
getSnapshotBeforeUpdate
componentDidUpdate
在更新结束和被调用,首次渲染不会触发它,首次渲染触发的 componentDidMount 可以做的  DOM 操作或者发起请求,它也可以,只是更新渲染结束后不会再触发componentDidMount, 而触发的是它。可以基于更新前后的state或者props的变化来做出相应的请求或者操作
重点对于状态的更改需要做出判断
你也可以在
componentDidUpdate()中直接调用setState(),但请注意它必须被包裹在一个条件语句里,正如上述的例子那样进行处理,否则会导致死循环。
-------------------------------------------------------------------------------------------------------------------**
卸载
componentWillUnmount
componentWillUnmount()会在组件卸载及销毁之前直接调用。在此方法中执行必要的清理操作,例如,清除 timer,取消网络请求或清除在componentDidMount()中创建的订阅等。
componentWillUnmount()中不应调用setState(),因为该组件将永远不会重新渲染。组件实例卸载后,将永远不会再挂载它。
 
                
            
         
 
         浙公网安备 33010602011771号
浙公网安备 33010602011771号