[Day23] 在 Codecademy 学 React ~ Component Lifecycle 生命周期我不懂你QQ

前言

原本以为生命周期应该很好懂,
但我卡在别的地方,
不过快 12 点了啊我先 po 出我目前进度QQ
The Component Lifecycle

本日正文

https://ithelp.ithome.com.tw/upload/images/20210925/20129873bNKhtaPuYC.png
在这个章节 Codecademy 会不断提到 component lifecycle 分成三个最高的阶段:

  1. Mounting:当 component initial 并放到 DOM 上
  2. Updating:当 component 的 props, state 有所改变时
  3. Unmounting:当 component 从 DOM 上被移除

即时时间显示

而这边用了一个即时时间显示的例子来带入各个生命周期的教学。
首先我们一样先新增一个 Clock.js,
里面我先摆一个时间显示,
时间显示摆在一个 <div> 中:

<div>{这边预计要摆时间}</div>

但我们当然想要读取当下的时间,
所以我们要在 constructor 宣告一个 state 为 date,
值设定为 new Date()
像这样:

constructor(props) {
    super(props);
    this.state = {
      date: new Date(),
    };
  }

有了这个宣告之後,
我就可以回过头去改 <div> 里面的值了,
改成这样:

<div>{this.state.date.toLocaleTimeString()}</div>

(PS. toLocaleTimeString 的作用是转成所在时区的时间)

增加切换的按钮

而按钮最单纯先摆这样:

<button>隐藏时间</button>

可是我想要让按钮点了有显示时间、隐藏时间的功用,
该怎麽做?

在 constructor 中,
除了 date 的宣告之外,
还要再多宣告一个 toggleClock,
拿来控制时间的开关,
像这样:

constructor(props) {
    super(props);
    this.state = {
      date: new Date(),
      toggleClock: true
    };
  }

再来就是宣告一个 function,
当 toggleClock 是 true 就改为 false,
反之就改成 true,
像这样:

changeClock() {
    this.setState({ toggleClock: !this.state.toggleClock });
  }

再来就是到按钮的地方设定 onClick 事件时要执行 changeClock 的 function,
还有按钮的文字也要根据 toggleClock 是 true 或 false 而要有所变化,
像这样:

<button onClick={this.changeClock}>
  {this.state.toggleClock ? "隐藏时间" : "显示时间"}
</button>

可是这时候当你点击按钮却出现 error,
这边不要忘了宣告一个 function 後,
在 constructor 要让它 bind this:

this.changeClock = this.changeClock.bind(this);

setInterval

这样看起来似乎没有问题了,
但你发现时间好像不会跟着变化,
只会停在渲染网页当下的时间,对吧?

这边 Codecademy 告诉你可以使用 setInterval 做到计时的效果
(setInterval 大家应该不陌生,就是每隔一段时间就要执行一次 function)

但问题来了,setInterval 该放在哪里?

在这个章节 Codecademy 会不断提到 component lifecycle 分成三个最高的阶段:

  1. Mounting:当 component initial 并放到 DOM 上
  2. Updating:当 component 的 props, state 有所改变时
  3. Unmounting:当 component 从 DOM 上被移除

再让我们回想一下 lifecycle 的阶段,
这边你一定可以肯定绝对不会是把 setInterval 放在 Unmounting 阶段执行,
再来到目前为止我们最常使用的两个生命周期 function: render, constructor
这两个适合放吗?
constructor 显然不适合,因为只会在 component 被 mount 时执行一次。
render 呢?render 会在 mounting phase 及 updating phase 都被执行,
这样太过频繁了,
也不适合。

componentDidMount

这边 Codecademy 教了一个新的方法:componentDidMount()
顺序是这样的:

  1. The constructor
  2. render()
  3. componentDidMount()

https://ithelp.ithome.com.tw/upload/images/20210925/20129873huVmjMMxod.png

所以 componentDidMount 当 component 被渲染(render)之後才会执行,
而我们这边就试着把 setInterval 放在 componentDidMount 中间,
像这样:

componentDidMount() {
    const oneSecond = 1000;
    this.intervalID = setInterval(() => {
      this.setState({ date: new Date() });
    }, oneSecond);
  }

componentWillUnmount

看起来也有在运作了,
然後有 mount 当然也有 unmount,
但这个时间被隐藏起来的时候你当然也会希望这个计时器可以暂停,
避免在背後吃掉资源对吧?

所以 Codecademy 在这时候教了 componentWillUnmount,
意思是在 component unmount 时要执行的动作,
像这样:

componentWillUnmount() {
    clearInterval(this.intervalID);
  }![](http://)

但为了验证是不是真的有停下来我有故意在 componentDidMount 埋了 console.log 来看,

componentDidMount() {
    const oneSecond = 1000;
    this.intervalID = setInterval(() => {
      this.setState({ date: new Date() });
      console.log("时钟还在跑哦");
    }, oneSecond);
  }


结果发现隐藏时间後 console.log 还在执行,
表示没有停止计时=口=
我刚花很多时间在找停止计时不 work 的原因,
但目前还不确定问题是出在 component 没有 unmount 还是 this.intervalID 之类的,
但因为快 12 点了,
只好先停止 trouble shooting 了,
我先来 po 文orz

然後附上本日程序→ Day23 - Lifecycle (Codecademy)

後记

希望我明天找得出原因QQ


<<:  【Side Project】 菜单内容2-ORM( SqlSugar)

>>:  VM功能与参数详解

[Q1][STM32G4系列] TIMER观察 - 使用TIMER触发ADC,透过DMA方式结合

前言 以TIMER为主要观察源,使用TIMER触发ADC,透过DMA结合,同时观察ADC中断副程序,...

Day4 Python基础语法二

今天的影片内容为介绍在Python中常用来储存资料的形式,分别是串列(list)、元祖(tuple)...

第48天-学习 crontab 工作排程

今天进度 鸟哥私房菜 - 第十五章、例行性工作排程(crontab) 我在 Crontab.guru...

[13th][Day7] container 处理程序

在 container 中运行後台任务 docker exec -d daemon_eric tou...

Day13 Vue directives(v-if & v-show)

嗨~今天又见面了,昨天我们了解了Evnet Handing後我们今天要继续来讲条件渲染v-if、v-...