6 State and Lifecycle

状态和生命周期

在第四章节中介绍 更新React element --- 这种方法不可取

function tick() {
  const element = (
    <div>
      <h1>Hello, world!</h1>
      <h2>It is {new Date().toLocaleTimeString()}.</h2>
    </div>
  );
  ReactDOM.render(
    element,
    document.getElementById('root')
  );
}

setInterval(tick, 1000);

本章节将介绍更实用的更新 与封装

封装Clock Component

ReactDOM.render(
  <Clock />,
  document.getElementById('root')
);

State 类似 props ,但是它是私有的完全由组件控制。

1 创建ES6 class 继承React.Component

2 添加render()方法

3 将 element中主体移到render()中

4 通过new Date() 替换成this.props.date 通过props中获取date

5 在<Clock />中添加 date属性

class Clock extends React.Component {
  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.props.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

实用状态优化

添加本地状态

1 移除date从props获取 --- this.props.date 替换成this.state.date

class Clock extends React.Component {
  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

2 添加构造方法 初始化 this.state

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }

  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

接下来 设置Clock自动更新显示时间

添加生命周期方法到类中

一个应用中可能有很多组件,组件销毁是释放组件资源很重要

monunt --- 当clock组件第一次渲染DOM 給clock设置计数器被称为 安装

unmount - 当clock组件被DOM中删除 清除clock的计数器 被称为 卸载

class Clock extends React.Component {
    constructor(props) {
        super(props);
        this.state = {date: new Date()};
    }

    //组件被挂载
    componentDidMount() {

    }
    //组件被卸载
    componentWillUnmount() {

    }

    render() {
        return (
            <div>
                <h1>Hello, world!</h1>
                <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
            </div>
        );
    }
}

当组件显示在DOM中会执行componentDidMount()回调,可以在这里创建定时器

componentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),
      1000
    );
  }

当组件从DOM中移除会执行componentWillUnmount()回调,可以在这里清楚定时器

 componentWillUnmount() {
    clearInterval(this.timerID);
  }

最终实现 每秒更新显示时间

1 ReactDOM.render 渲染是加载clock组件

2 首先执行构造方法

3 再执行render

4 当显示在DOM之后执行componentDidMount 设置定时器 1s执行一次tick(),在tickzhong 改变状态 从而页面会执行render

5 当组件销毁 执行componentWillUnmount 清楚 定时器

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }

  componentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),
      1000
    );
  }

  componentWillUnmount() {
    clearInterval(this.timerID);
  }

  tick() {
    this.setState({
      date: new Date()
    });
  }

  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

ReactDOM.render(
  <Clock />,
  document.getElementById('root')
);

正确使用setState()

1 不要直接修改state ---- 唯一可以直接分配shis.state 是构造方法
// Wrong
this.state.comment = 'Hello';
// Correct
this.setState({comment: 'Hello'});
2 设置state 更新 可能是异步的

React 可能将多个setstate() 在一次更新中处理

想要及时更新 使用

// Correct
this.setState((prevState, props) => ({
  counter: prevState.counter + props.increment
}));
// Correct
this.setState(function(prevState, props) {
  return {
    counter: prevState.counter + props.increment
  };
});

6 状态更新合并

  constructor(props) {
    super(props);
    this.state = {
      posts: [],
      comments: []
    };
  }
  componentDidMount() {
    fetchPosts().then(response => {
      this.setState({
        posts: response.posts
      });
    });

    fetchComments().then(response => {
      this.setState({
        comments: response.comments
      });
    });
  }

生命周期补充

 //1 创建阶段 处理props的默认值
  getDefaultProps(){
    console.log('getDefaultProps');
  }

// 2 作用于组件的实例,在实例创建时调用一次,用于初始化每个实例的state,此时可以访问this.props。
  getInitialState(){
      console.log('getInitialState');
  }


    // 3 在完成首次渲染之前调用,此时仍可以修改组件的state。
  componentWillMount(){


  }


/** 4 render
 * 必选的方法,创建虚拟DOM,该方法具有特殊的规则:
 只能通过this.props和this.state访问数据
 可以返回null、false或任何React组件
 只能出现一个顶级组件(不能返回数组)
 不能改变组件的状态
 不能修改DOM的输出
 */
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.welcome}>
          Welcome to React Nativddde!
        </Text>
        <Text style={styles.instructions}>
          To get started, edit index.android.js
        </Text>
        <Text style={styles.instructions}>
          Double tap R on your keyboard to reload,{'\n'}
          Shake or press menu button for dev menu
        </Text>
      </View>
    );
  }

/**
 * 5 componentDidMount
 * 真实的DOM被渲染出来后调用,在该方法中可通过this.getDOMNode()访问到真实的DOM元素。
 * 此时已可以使用其他类库来操作这个DOM。
 *
 * 在服务端中,该方法不会被调用。
 *
 * */
  componentDidMount(){

  }

  /** 6 componentWillReceiveProps
   * 组件接收到新的props时调用,
   * 并将其作为参数nextProps使用,
   * 此时可以更改组件props及state。
   * */
  componentWillReceiveProps(nextProps){
      if (nextProps.bool) {
          this.setState({
              bool: true
          });
      }
  }


    /**
     * 7.shouldComponentUpdate
     * 组件是否应当渲染新的props或state,返回false表示跳过后续的生命周期方法,通常不需要使用以避免出现bug。在出现应用的瓶颈时,可通过该方法进行适当的优化。
     * 在首次渲染期间或者调用了forceUpdate方法后,该方法不会被调用
     * */
    shouldComponentUpdate(nextProps, nextState){

    }


    /**
     * 8.componentWillUpdate
     * 接收到新的props或者state后,进行渲染之前调用,此时不允许更新props或state。
     * */
    componentWillUpdate(nextProps, nextState){

    }

    /**
     * 9.componentDidUpdate
     * 完成渲染新的props或者state后调用,此时可以访问到新的DOM元素。
     * */
    componentDidUpdate(prevProps, prevState){

    }

    /**
     * 10.componentWillUnmount
     * 组件被移除之前被调用,可以用于做一些清理工作,
     * 在componentDidMount方法中添加的所有任务都需要在该方法中撤销,
     * 比如创建的定时器或添加的事件监听器。
     * */
    componentWillUnmount(){

    }

results matching ""

    No results matching ""