React State与生命周期详细介绍

目录
  • 一、State
    • 1.1 类组件中的State
    • 1.2 函数组件中的State
  • 二、React生命周期
    • 2.1 挂载
    • 2.2 更新
    • 2.3 卸载
    • 2.4 函数式组件useEffect
  • 三、总结

一、State

在React当中,当你更新组件的state,然后新的state就会重新渲染到页面中。在这个时候不需要你操作任何DOM。这和vue中组件的data中的数据是相似的。

1.1 类组件中的State

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>State</title>
    <script src="https://cdn.staticfile.org/react/16.8.0/umd/react.development.js"></script>
    <script src="https://cdn.staticfile.org/react-dom/16.8.0/umd/react-dom.development.js"></script>
    <!-- 生产环境中不建议使用 -->
    <script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
  </head>
  <body>
    <div id="app"></div>
    <script type="text/babel">
      class Clock extends React.Component {
        constructor(props) {
          super(props);
          this.state = { title: "React State", date: new Date() };
          this.handleClick = this.handleClick.bind(this);
        }
        handleClick() {
          this.setState({ date: new Date() });
        }
        render() {
          return (
            <div>
              <p>{this.state.title}</p>
              <p>现在是 {this.state.date.toLocaleTimeString()}.</p>
              <button onClick={this.handleClick}>更新时间</button>
            </div>
          );
        }
      }
      ReactDOM.render(<Clock />, document.getElementById("app"));
    </script>
  </body>
</html>

类组件需要在constructor中定义this.state对象,其对应的属性就是需要使用的state,例如上面代码中的title和date属性,在render函数中通过this.sate.XXX调用。

注意,修改state需要调用this.setState方法,不可以直接对state进行赋值。

这里的handleClick是按钮的点击事件,点击按钮后,调用setState方法重新为date赋值,此时页面会自动更新。

1.2 函数组件中的State

函数组件没有state => React v16.8.0推出Hooks API,其中的一个API叫做useState可以解决问题。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>State</title>
    <script src="https://cdn.staticfile.org/react/16.8.0/umd/react.development.js"></script>
    <script src="https://cdn.staticfile.org/react-dom/16.8.0/umd/react-dom.development.js"></script>
    <!-- 生产环境中不建议使用 -->
    <script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
  </head>
  <body>
    <div id="app"></div>
    <script type="text/babel">
      const Clock = (props) => {
        const [n, setN] = React.useState(0);
        function addNum() {
          setN(n + 1);
        }
        return (
          <div>
            <p>现在的n是 {n} .</p>
            <button onClick={addNum}>n+1</button>
          </div>
        );
      };
      ReactDOM.render(<Clock />, document.getElementById("app"));
    </script>
  </body>
</html>

可以看到,在函数组件中使用state需要借助useState,并且useState会返回setXXX方法用于修改定义的state,相比于类组件,函数组件更加简洁,而且不用关注修改state时的this指向问题。

二、React生命周期

组件的生命周期可分成三个状态:

  • Mounting(挂载):已插入真实 DOM
  • Updating(更新):正在被重新渲染
  • Unmounting(卸载):已移出真实 DOM

2.1 挂载

当组件实例被创建并插入 DOM 中时,其生命周期调用顺序如下:

  1. constructor(): 在 React 组件挂载之前,会调用它的构造函数。
  2. getDerivedStateFromProps():在调用 render 方法之前调用,并且在初始挂载及后续更新时都会被调用。
  3. render(): render() 方法是 class组件中唯一必须实现的方法。
  4. componentDidMount(): 在组件挂载后(插入 DOM 树中)立即调用。

render() 方法是 class 组件中唯一必须实现的方法,其他方法可以根据自己的需要来实现。

2.2 更新

每当组件的 state 或 props 发生变化时,组件就会更新。

当组件的 props 或 state 发生变化时会触发更新。组件更新的生命周期调用顺序如下:

  1. getDerivedStateFromProps(): 在调用 render 方法之前调用,并且在初始挂载及后续更新时都会被调用。根据shouldComponentUpdate() 的返回值,判断 React 组件的输出是否受当前 state 或 props更改的影响。
  2. shouldComponentUpdate():当 props 或 state 发生变化时,shouldComponentUpdate() 会在渲染执行之前被调用。
  3. render(): render() 方法是 class 组件中唯一必须实现的方法。
  4. getSnapshotBeforeUpdate(): 在最近一次渲染输出(提交到 DOM节点)之前调用。
  5. componentDidUpdate(): 在更新后会被立即调用。

render() 方法是 class 组件中唯一必须实现的方法,其他方法可以根据自己的需要来实现。

2.3 卸载

当组件从 DOM 中移除时会调用如下方法:

componentWillUnmount(): 在组件卸载及销毁之前直接调用。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Lifecycle</title>
    <script src="https://cdn.staticfile.org/react/16.8.0/umd/react.development.js"></script>
    <script src="https://cdn.staticfile.org/react-dom/16.8.0/umd/react-dom.development.js"></script>
    <!-- 生产环境中不建议使用 -->
    <script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
  </head>
  <body>
    <div id="app"></div>
    <script type="text/babel">
      class Button extends React.Component {
        constructor(props) {
          super(props);
          this.state = { data: 0 };
          this.setNewNumber = this.setNewNumber.bind(this);
        }
        setNewNumber() {
          this.setState({ data: this.state.data + 1 });
        }
        render() {
          return (
            <div>
              <button onClick={this.setNewNumber}>INCREMENT</button>
              <Content myNumber={this.state.data}></Content>
            </div>
          );
        }
      }
      class Content extends React.Component {
        componentWillMount() {
          console.log("Component WILL MOUNT!");
        }
        componentDidMount() {
          console.log("Component DID MOUNT!");
        }
        componentWillReceiveProps(newProps) {
          console.log("Component WILL RECEIVE PROPS!");
        }
        shouldComponentUpdate(newProps, newState) {
          return true;
        }
        componentWillUpdate(nextProps, nextState) {
          console.log("Component WILL UPDATE!");
        }
        componentDidUpdate(prevProps, prevState) {
          console.log("Component DID UPDATE!");
        }
        componentWillUnmount() {
          console.log("Component WILL UNMOUNT!");
        }
        render() {
          return (
            <div>
              <h3>{this.props.myNumber}</h3>
            </div>
          );
        }
      }
      ReactDOM.render(
        <div>
          <Button />
        </div>,
        document.getElementById("app")
      );
    </script>
  </body>
</html>

注意:只有类组件才有生命周期。函数组件每次都是重新运行函数,旧的组件即刻被销毁。

2.4 函数式组件useEffect

与使用state需要借助useState一样,在函数组件中,我们需要借助可以借助react提供的方法在函数式组件中实现“生命周期”,它就是useEffect

useEffect 给函数组件增加了操作副作用的能力。它跟 class 组件中的

componentDidMount、componentDidUpdate 和 componentWillUnmount 具有相同的用途,只不过被合并成了一个 API。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>useEffect</title>
    <script src="https://cdn.staticfile.org/react/16.8.0/umd/react.development.js"></script>
    <script src="https://cdn.staticfile.org/react-dom/16.8.0/umd/react-dom.development.js"></script>
    <!-- 生产环境中不建议使用 -->
    <script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
  </head>
  <body>
    <div id="app"></div>
    <script type="text/babel">
      const Clock = (props) => {
        const [n, setN] = React.useState(0);
        function addNum() {
          setN(n + 1);
        }
        React.useEffect(() => {
          console.log(n);
        });
        return (
          <div>
            <p>现在的n是 {n} .</p>
            <button onClick={addNum}>n+1</button>
          </div>
        );
      };
      ReactDOM.render(<Clock />, document.getElementById("app"));
    </script>
  </body>
</html>

可以看到,上面的使用useEffect时,挂载或者销毁时,都会触发useEffect中的函数,那么如何使用useEffect模拟生命周期呢?

//    只在组件挂载后显示,只需要加个空数组做参数即可
    useEffect(() => {
        document.title = `You clicked ${count} times`;
    },[]);
//    销毁阶段
    useEffect(() => {
        return ()=>{
				console.log("销毁阶段")
			}
    });

三、总结

可以看到,类组件和函数组件在State和生命周期上区别还是非常大的,函数式组件需要调用react提供的hooks(钩子函数,非常重要,后面会专门学习)来实现类组件对于的功能。

学习过程中,我发现react类组件类似于vue2的选项式api组件,而函数组件则vue3组合式api十分相似。

到此这篇关于React State与生命周期详细介绍的文章就介绍到这了,更多相关React State内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 详解React 的数据流和生命周期

    目录 数据流和生命周期 数据和数据流 不可变状态 props 只使用 props 的组件 组件通信 单向数据流 渲染和生命周期 生命周期方法简介 spug 使用了哪些生命周期方法 父子组件的生命周期 数据流和生命周期 如何处理 React 中的数据,组件之间如何通信,数据在 React 中如何流动? 常用的 React 生命周期方法以及开源项目 spug 中使用了哪些生命周期方法? 数据和数据流 虽然也有很多静态网站,但人们使用的大多数网站都充满了随时间变化的数据. state 和 props

  • 使用useEffect模拟组件生命周期

    目录 useEffect模拟组件生命周期 让函数组件模拟生命周期 初始化 更新阶段 卸载阶段 useEffect实现componentWillUnmount生命周期函数 阐述 useEffect 解绑副作用 useEffect的第二个参数 useEffect模拟组件生命周期 让函数组件模拟生命周期 默认函数组件没有生命周期 函数组件是一个纯函数,执行完即销毁,自己无法实现生命周期 通过Effect hook把生命周期“钩”到纯函数中     // 模拟 class 组件的 DidMount 和

  • React useEffect异步操作常见问题小结

    目录 三个常见的问题: 一.react hooks发异步请求 二.如何在组件加载的时候发起异步任务 三.如果在响应回来之前组件被销毁了会怎样? 四.如何在组件交互时发起异步任务 为什么两种写法会有差异呢? 五.其他陷阱 总结 useEffect 和异步任务搭配使用的时候会遇到的一些坑总结. 三个常见的问题: 1.如何在组件加载的时候发起异步任务 2.如何在组件交互的时候发起异步任务 3.其他陷阱 一.react hooks发异步请求 1.使用useEffect发起异步任务,第二个参数使用空数组可

  • React State与生命周期详细介绍

    目录 一.State 1.1 类组件中的State 1.2 函数组件中的State 二.React生命周期 2.1 挂载 2.2 更新 2.3 卸载 2.4 函数式组件useEffect 三.总结 一.State 在React当中,当你更新组件的state,然后新的state就会重新渲染到页面中.在这个时候不需要你操作任何DOM.这和vue中组件的data中的数据是相似的. 1.1 类组件中的State <!DOCTYPE html> <html lang="en"&

  • Flutter有无状态类与State及生命周期详细介绍

    目录 无状态类 有状态类 状态 State生命周期 Flutter中的生命周期类似于Vue.React中的生命周期一样,有初始化.状态更新.停用.销毁等. 在React中,组件分为函数式组件和类式组件,它们的区别就是一个无状态.一个有状态.那么在Flutter中亦是如此,它有两种类,一种是无状态类,一种是有状态类.其生命周期的使用就是有状态类的特定用法. 无状态类 无状态类内部有build方法,在表面上看 每次数据更新都会执行build方法.但实际上,在组件树中,当每次数据发生变更时,无状态类都

  • Maven构建生命周期详细介绍

    什么是构建生命周期 构建生命周期是一组阶段的序列(sequence of phases),这些构建生命周期中的每一个由构建阶段的不同列表定义,其中构建阶段表示生命周期中的阶段. 例如,默认(default)的生命周期包括以下阶段(注意:这里是简化的阶段,用于生命周期阶段的完整列表): 验证(validate) - 验证项目是否正确,所有必要的信息可用 编译(compile) - 编译项目的源代码 测试(test) - 使用合适的单元测试框架测试编译的源代码.这些测试不应该要求代码被打包或部署 打

  • Android Activity的生命周期详细介绍

    Android Activity的生命周期详细介绍 生命周期描述的是一个类从创建(new出来)到死亡(垃圾回收)的过程中会执行的方法.在这个过程中,会针对不同的生命阶段调用不同的的方法. Activity是Android中四大组件之一,是最常见的应用组件,也是用的最多的组件,它能够提供一个界面与用户进行交互.Activity从创建到销毁有多种状态,从一种状态到另一种状态时会激发相应的回调方法,这些回调方法包括:onCreate  onDestory  onStart  onStop  onRes

  • Mybatis结果集映射与生命周期详细介绍

    目录 一.ResultMap结果集映射 1.设计思想 2.resultMap的应用场景 二.生命周期和作用域 一.ResultMap结果集映射 1.设计思想 对简单的语句做到零配置,对于复杂一点的语句,只需要描述语句之间的关系就行了 2.resultMap的应用场景 下面这个是我的数据库表 然后这是我们对应的Java实体类User2,除了有参构造外,它还定义了一个无参构造,而且用户id字段为userId,与数据库表中的id不一致 我们在执行查询方法后可以发现,实体类中的userId和数据库表中的

  • React组件的生命周期详细描述

    目录 一.什么是生命周期 二.装载过程 1.constructor 2.render 3.componentWillMount和componentDidMount 三.更新过程 1.componentWillReceiveProps(nextProps) 2.shouldComponentUpdate(nextProps, nextState) 3.componentWillUpdate和componentDidUpdate 4.触发render 四.卸载过程 五.生命周期流程 1.第一次初始化

  • Docker Runc容器生命周期详细介绍

    Docker Runc容器生命周期 容器的生命周期涉及到内部的程序实现和面向用户的命令行界面,runc内部容器状态转换操作.runc命令的参数定义的操作.docker client定义的容器操作是不同的,比如对于docker client的create来说, 语义和runc就完全不同,这一篇文章分析runc的容器生命周期的抽象.内部实现以及状态转换图.理解了runc的容器状态转换再对比理解docker client提供的容器操作命令的语义会更容易些. 容器生命周期相关接口 最基本的require

  • 微信小程序(五)页面生命周期详细介绍

    这里只要熟悉页面的基本生命周期即可,业务在指定生命周期函数内书写. 以下是官网给出的生命周期函数方法和状态图 上面的生周期函数图对于做Android 或者IOS的来书理解起来应该不是难事,具体怎么掌握只有慢慢尝试和摸索 代码处理: 这里的代码主需要对使用创建项目时index目录下文件处理下就行,至于跳转后的页面用的还是logs不需要更改!下面贴下代码注释也比较详细 index.wxml <!--index.wxml--> <view class="container"

  • Android Service类与生命周期详细介绍

    Android  Service类与生命周期 Service是Android四大组件与Activity最相似的组件,都代表可执行的程序,区别在于Service一直在后台运行且没有用户界面. 1.Service的类图和生命周期 先来看看Service的类图: 接下来看看Service的生命周期: 2.开发Service (1)开发Service需要两步: 第1步:定义子类,继承Service 第2步:在AndroidManifest.xml文件中配置Service (2)创建Service pub

  • Android  Service类与生命周期详细介绍

    Android  Service类与生命周期 Service是Android四大组件与Activity最相似的组件,都代表可执行的程序,区别在于Service一直在后台运行且没有用户界面. 1.Service的类图和生命周期 先来看看Service的类图: 接下来看看Service的生命周期: 2.开发Service (1)开发Service需要两步: 第1步:定义子类,继承Service 第2步:在AndroidManifest.xml文件中配置Service (2)创建Service pub

随机推荐