react生命周期(新)

  • 废弃掉了三个生命周期: componentWillMount,componentWillReceiveProps,componentWillUpdate
  • 新增了两个生命周期:static getDerivedStateFromProps,getSnapshotBeforeUpdate
  • getDerivedStateFromProps相当于原来的componentWillMount和componentWillReceiveProps
  • getDerivedStateFromProps的有时候需要配合componentDidUpdate使用。

1.代码

import React, { Component } from "react";
import ReactDOM from "react-dom";

import "./styles.css";

function fetchData() {
  return new Promise(function(resolve, reject) {
    setTimeout(function() {
      resolve("获取ajax数据");
    }, 2000);
  });
}

class Welcome extends Component {
  constructor(props) {
    console.log("constructor", props);
    super(props);
    this.state = {
      color: props.color
    };
  }

  static getDerivedStateFromProps(nextProps, prevState) {
    console.log("getDerivedStateFromProps", nextProps, prevState);
    if (nextProps.color !== prevState.color) {
      return {
        color: nextProps.color
      };
    }
    return null; // 1 
    // return {color: "orange"};   //2. 相对于componenentWillMount中的直接同步setState
  }

  componentDidMount() {
    console.log("componentDidMount");
    //3. this.setState({ color: "yellow" });
  }

  shouldComponentUpdate(nextProps, nextState) {
    console.log("shouldComponentUpdate", nextProps, nextState);
    return true;
  }

  getSnapshotBeforeUpdate() {
    console.log("getSnapshotBeforeUpdate");
    return null
  }
  componentDidUpdate(prevProps, prevState) {
    console.log("componentDidUpdate", prevProps, prevState);
  }

  componentWillUnmount() {
    console.log("componentWillUnmount");
  }

  changeColor = () => {
    this.setState({ color: "#ddd" });
  };
  render() {
    console.log("render", this.state.color);
    return (
      <div style={{ background: this.state.color }}>
        <h1>react 旧的生命周期</h1>
        <p>{this.state.color}</p>
        <button onClick={this.changeColor}>内部change color</button>
      </div>
    );
  }
}

class App extends Component {
  state = {
    currentColor: "red",
    colorIndex: 0
  };

  changeColor = () => {
    let colors = ["red", "yellow", "blue", "green", "pink"];
    let { colorIndex } = this.state;
    colorIndex = ++colorIndex % 5;
    console.log(colorIndex);
    this.setState({
      currentColor: colors[colorIndex],
      colorIndex
    });
  };

  render() {
    let { currentColor } = this.state;
    return (
      <div className="App">
        <Welcome color={currentColor} />
        <hr />
        <button onClick={this.changeColor}>外部change color</button>
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

2. 输出结果

1.直接输出
constructor {color: "red"}
getDerivedStateFromProps {color: "red"} {color: "red"}
render red
componentDidMount
2.componentDidMount中改变state
  • ①在componentDidMount中改变state,即将代码注释3处打开,可见componentDidMount会重新触发一次render,注意这里没有ajax的异步请求,直接setState就会重新渲染!!!
constructor {color: "red"}
getDerivedStateFromProps {color: "red"} {color: "red"}
render red
componentDidMount
getDerivedStateFromProps {color: "red"} {color: "yellow"}
shouldComponentUpdate {color: "red"} {color: "red"}
render red
getSnapshotBeforeUpdate
componentDidUpdate {color: "red"} {color: "red"}

☆☆☆☆☆注意☆☆☆☆☆
上面在componentDidMount中setState想将子组件color变成yellow,但是最后还是渲染的red,是应为componentDidMount之后又调用了getDerivedStateFromProps ,导致下面这段代码再次执行,从而又把父组件的颜色渲染给了子组件,应为父组件颜色没变,仍然是一开始的red,所以子组件color又变成red了,第4点中改变子组件state值,一样会导致这个问题,即子组件设置setState
不变化。
解决方案目前知道的有两种,一种是getDerivedStateFromProps 配合componentDidUpdate 使用。另一种是别在子组件中setState,全在父组件中来控制变量(或者在redux中管理)

if (nextProps.color !== prevState.color) {
  return {
    color: nextProps.color
  };
}
3.改变父组件传入值,从而改变子组件state

点击父组件改变颜色按钮,改变父组件传入的props的值,查看结果
getDerivedStateFromProps => shouldComponentUpdate => render => getSnapshotBeforeUpdate => componentDidUpdate

getDerivedStateFromProps {color: "yellow"} {color: "red"}
shouldComponentUpdate {color: "yellow"} {color: "yellow"}
render yellow
getSnapshotBeforeUpdate
componentDidUpdate {color: "red"} {color: "red"}
4.改变子组件state值

点击子组件改变颜色按钮,改变子组件state值,查看结果
getDerivedStateFromProps => shouldComponentUpdate => render => getSnapshotBeforeUpdate => componentDidUpdate

getDerivedStateFromProps {color: "red"} {color: "yellow"}
shouldComponentUpdate {color: "red"} {color: "red"}
render red
getSnapshotBeforeUpdate
componentDidUpdate {color: "red"} {color: "red"}

☆☆☆☆☆注意☆☆☆☆☆
问题和上面第2点注意处一样,子组件改变state不变。

实例网站

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容