首页 > 编程语言 >React状态 和 JavaScript箭头函数

React状态 和 JavaScript箭头函数

时间:2023-03-29 18:24:30浏览次数:48  
标签:timerID Clock componentDidMount JavaScript React 箭头 tick 1000

React状态 和 JavaScript箭头函数

在看 React 的状态时见到了 JS 的箭头函数,一时间没看明白。

React 状态

React 把组件看成是一个状态机(State Machines)。通过与用户的交互,实现不同状态,然后渲染 UI,让用户界面和数据保持一致。

在 React 中,当一个组件的状态发生改变时,React 会感知到状态的变化,并将其更新到 DOM 中。

先看一个界面上时钟的实现:

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }
 
  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>现在是 {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}
 
ReactDOM.render(
  <Clock />,
  document.getElementById('example')
);

这个时钟只通过 React 实现了控件的绑定,但还没有实时刷新的功能,所以,需要在代码中设置一个定时器使其能够每秒刷新一次,此处使用生命周期方法(钩子)实现:

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>现在是 {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}
 
ReactDOM.render(
  <Clock />,
  document.getElementById('example')
);

其中 componentDidMount()componentWillUnmount() 就是生命周期方法(钩子)。

当这个 Clock 组件输出到 DOM 后会执行 componentDidMount() 钩子,相当于组件的初始化,在上面,我们在这个方法中设置了一个定时器。

当这个 Clock 组件从 DOM 中移除后,会执行 componentWillUnmount() 钩子,通过初始化时设置的定时器的 ID this.timerID,可以卸载这个定时器。

在设置的定时器中执行了 tick() 方法,这个方法在执行时会设置 Clock 组件的状态,将 data 属性设置为当前的新的 Date 对象,React 可以感知到 State 的改变,会调用 render() 方法重新渲染输出,且 React 可以对比前后内容的差距,只重新渲染有区别的内容,这样就实现了画面的更新。

JavaScript箭头函数

在上面的例子中,可以注意到在 componentWillUnmount() 方法中使用了箭头函数:

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

其中,setInterval(func, time) 方法为每过 time 就执行一次 func,在上面的例子中,就是每过 1000 毫秒(1秒)就执行一次 () => this.tick() 方法。

那为什么这里要使用箭头函数呢?我一开始的想法是这里只是为了装B,于是把它换掉了:

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

打开页面,时间显示了,但不会动了。(后面发现,此时将 this.tick() 换为 console.log(this),此时的 this 确实是 Clock,但为什么时间不动,也还不是很懂了。)

于是尝试使用匿名函数 function() 将 tick() 包装起来:

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

这次报错了,问题是 tick() 不是一个方法:

Uncaught TypeError TypeError: this.tick is not a function

此时我就无法理解了。在研究了半天后,通过将 this.tick() 换为 console.log(this) 发现,此时的 this 居然是 Window:

  componentDidMount() {
    this.timerID = setInterval(function(){
      console.log(this);
      this.tick();
      },1000
    );
  }
  // 控制台输出:
  // Window {window: Window, self: Window, document: #document, name: '', location: Location, …}
  // Uncaught TypeError TypeError: this.tick is not a function

在这个方法中,this 指代的是 Window,而 tick() 是 Clock 的方法,所以这个报错就很合理了。

又研究了一会后发现,匿名函数中的 this 指代的就是 Window,所以直接使用匿名函数是行不通的,除非在外部保存 Clock 对象,再将对 this 的调用改为对 Clock 对象的调用:

  componentDidMount() {
    let that = this;
    this.timerID = setInterval(function(){
      console.log(that);
      that.tick();
      },1000
    );
  }
  // 控制台输出:
  // Clock {props: {…}, context: {…}, refs: {…}, updater: {…}, state: {…}, …}

这下就正常了,但这一会 that,一会 this 的,确实有点麻烦和乱了。所以这也是箭头函数存在的意义了(先撤了)。

标签:timerID,Clock,componentDidMount,JavaScript,React,箭头,tick,1000
From: https://www.cnblogs.com/qiyuanc/p/Front5.html

相关文章

  • JavaScript系列 -> 字符串方法 replace 的第二个参数为函数
    本篇文章要介绍,当字符串的replace方法第二个参数为函数的使用。示例代码:functionfn(str){this.str=str;}fn.prototype.format=function(){vararg=......
  • JavaScript快速入门
    JavaScript1.引入方式1.1内部脚本,将JS代码定义在HTML页面种JS代码必须在<script>标签之中可以在HTML文件任意位置一般放在<body>体标签底部,改善运行速度1.2外部......
  • Vue2使用setup、ref、reactive等Vue3的组合式api
    有些同学想在当前项目中体验Vue3组合式api,setup、ref、reactive等,而且一步就可以升级到Vue3,但是vue确实2.x版本,不改变当前版本怎么办呢?vue2.7.0开始自带composition-api可......
  • 思考 React Hook 和 Vue 组合式 API
    Vue组合式API优化周期函数Vue2比如mounted周期中有很多获取数据的逻辑都在这里,在updated周期中又有很多更新的逻辑在这里。在老版本的Vue3文档中讲解组合式AP......
  • JavaScript Promises, async/await
    JavaScriptPromises,async/await这篇博客不是讲如何使用Promise,是一个学习总结。是我自己对Promise的理解。newPromise()的时候,传一个executor给Promise.......
  • webpack构建React、TSX项目(一)
    此篇主要是记录下webpack构建react项目的过程。前言:为什么想起来通过webpack去构建react的项目呢?现在可以通过cra或者vite或其他脚手架去构建比较省事。主要还是想要了解下w......
  • javascript中出现undefined的四种情况
    javascript中出现undefined的四种情况https://www.jianshu.com/p/b0700cce78c8一,函数没有返回值,或者返回值为空,出现undefined例:1)functionshow(){//没有返回值}vara=sh......
  • react生命周期
    componentWillMount:16版本就废弃了,相当于Vue中created;componentDidMount:会在组件挂载后(插入DOM中)立即调用;相当于Vue中的onMounted;componentDidUpdate(prevProps,pr......
  • 转载:JavaScript文字转语音_SpeechSynthesisUtterance语音合成的使用
    原文链接:https://mp.weixin.qq.com/s?__biz=MjM5MDA2MTI1MA==&mid=2649118413&idx=3&sn=3385dee75bcffa307baa79c3cde4095b&chksm=be587160892ff87605cf347eddad2ad7a55a95......
  • Javascript 加密解密方法
    本文链接Javascript和我之前发的python加密以及go加密解密不一样不需要导那么多的库只需要安装几个库其中需要了解最多的crypto-js具体就不多介绍了直接上官......