[Day22] 在 Codecademy 学 React ~ 原来 useState 就是 this.state + this.setState 啊!

前言

其实你知道吗?
今天要讲的 this.state this.setState 其实就是之前介绍过的 useState 耶!!!!!!!!!!!!!!
有兴趣的人可以右转这两篇看一下→
[Day14] 学 Reactstrap 就离 React 不远了 ~ 用 Navbar 认识 useState
[Day15] 学 Reactstrap 就离 React 不远了 ~ 用 Tooltips 熟悉 useState

但是学过 useState 的我回过头去学 this.setState 反而觉得有点吃力orz
这样我好难想像完全从零开始学 this.setState 的人会怎样哦orz
那就正式开始吧! this.state

本日正文

this.state - 状态

其实今天的语法我不晓得要怎麽讲解比较好XD
虽然在 Codecademy 有一步一步做,
但是我到现在还是搞不太懂的语法 Codecademy 的说明我还是参不太透XD
所以我决定先把它当既定文法先记下来再说了XD
(用多次一点我搞不好就会突然顿悟了?)

先直接讲结论好了,
不同於昨天讲的 this.props
属性只有在一开始 initial 或是在 component 被指定一次後就不能改变了,
this.state(状态)的值是可以随着与元件的互动改变的!
例如我今天天气一开始很好,但後来天气变差了,开始下雨。
上面这句话的叙述中,「天气」就是一种状态,而不是属性。

然後在 React 要用 this.state 宣告状态的语法是这样的:

class Weather extends React.Component {
  constructor(props) {
    super(props);
    this.state = { weather: 'sunny' };
  }
}

完全看不懂 constructor(props)super(props) 是什麽XD
先当成文法背起来,
後面再补充说明XD

那我如果要在页面上显示我现在心情状态该怎麽做?

跟昨天的 props 很像哦,
this.state.状态 就可以取得上面所宣告的状态:

render() {
    return (
      <h1>
        今天天气:{this.state.weather}!
      </h1>
    );
  }

把全部程序放在昨天范例试试看吧!
在这边新增一个 Weather.js,
宣告一个 Weather 的 component,
在里面宣告 weather 的 state,
并在 render 渲染一个 <h1> 内容为 {this.state.weather}
像这样:

import React from "react";

export class Weather extends React.Component {
  constructor(props) {
    super(props);
    this.state = { weather: 'sunny' };
  }
  render() {
    return <h1>今天天气:{this.state.weather}!</h1>;
  }
}

然後在 App.js 引入 Weather.js 中的 Weather 的 component,
并在 <div></div> 放入 <Weather />
像这样:

... (略)
import { Weather } from "./Weather.js";

export default function App() {
  return (
    <div className="App">
      ... (略)
      <Weather />
    </div>
  );
}

最後结果是:
https://ithelp.ithome.com.tw/upload/images/20210924/20129873hqBK24Ruu8.png

this.setState - 改变状态

上面有提到状态的值是可以随着与元件的互动改变的!
所以这边就开始要讲如何改变状态了,
首先我先在 Weather.js 天气叙述下面放一个按钮「改变天气」,
打算让它做的事就是按下去之後 sunny 跟 rainy 互换,
先宣告一个 <button>

render() {
    return (
      <div>
        <h1>今天天气:{this.state.weather}!</h1>
        <button>改变天气</button>
      </div>
    )
}

然後在 Weather.js constructor(props) {} 区块外面,
下方插入以下程序:

changeWeather() {
    const newWeather = this.state.weather == 'sunny' ? 'rainy' : 'sunny';
    this.setState({ weather: newWeather });
  }

这边的意思是宣告一个 function changeWeather,
里面去判断 weather 状态是不是 sunny,是的话 newWeather 就被指定为 rainy,
不是的话 newWeather 就被指定为 sunny,
然後再将 weather 状态的值改为 newWeather 的值。

然後又有我不懂的语法了XD
一样先照抄,
这次要在 constructor(props) {} 区块里面,
this.state = { weather: "sunny" }; 下方插入以下程序:

this.changeWeather = this.changeWeather.bind(this);

到这边只是把天气状态跟改变天气状态宣告好而已,
还差一步,
就是要把按钮的 onClick 绑成改变天气状态的 function,
像这样:

<button onClick={this.changeWeather}>改变天气</button>

最後 Weather.js 的程序全部会长这样:

import React from "react";

export class Weather extends React.Component {
  constructor(props) {
    super(props);
    this.state = { weather: "sunny" };
    this.changeWeather = this.changeWeather.bind(this);
  }

  changeWeather() {
    const newWeather = this.state.weather == 'sunny' ? 'rainy' : 'sunny';
    this.setState({ weather: newWeather });
  }

  render() {
    return (
      <div>
        <h1>今天天气:{this.state.weather}!</h1>
        <button onClick={this.changeWeather}>改变天气</button>
      </div>
    );
  }
}

让我们看一下执行结果:

this.state + this.setState = useState

所以这边兜回去文章前言一下,
有没有觉得今天讲的这一段

constructor(props) {
    super(props);
    this.state = { weather: "sunny" };
    this.changeWeather = this.changeWeather.bind(this);
  }

  changeWeather() {
    const newWeather = this.state.weather == 'sunny' ? 'rainy' : 'sunny';
    this.setState({ weather: newWeather });
  }

整个意思长得很像之前所用的 useStatesetXXX 呢?
useState 可以改写成这样:

const [weather, setWeather] = useState('sunny');
setWeather('rainy');

其实这根本就是前面那一段的综合体吧XD
这边也可以参考之前大大在铁人赛文章的说明→ 【React.js入门 - 13】 useState - 在function component用state

为什麽有 constructor(props) 啊?

现在回过头看一下不懂的语法好了XD
constructor 牵扯到 React 的 LifeCycle (生命周期),
https://ithelp.ithome.com.tw/upload/images/20210924/20129873nCdepXdc8v.png
可以看一下这张生命周期图,
constructor 落在 render 之前,
所以我个人的解读是在正式渲染元件到 DOM 之前,
要先把会用到的 props, state 等建置起来。

这边还有一篇大大写的文章 [第二十一周] React 生命周期: 建立初期 constructor、componentDidMount
但我还没上到 LifeCycle (生命周期) 章节,
所以这篇文章我还看不懂XD

为什麽又有 super(props) 啊?

再来 super(props) 又是什麽XD
可以参考大大写的这篇文章:为什麽我们要写 super(props) ?

在 JavaScript 中,super 会参照父类别的建构子。(在我们的例子当中,它会指向 React.Component 的实作。)

https://ithelp.ithome.com.tw/upload/images/20210924/20129873TnTvZH5Ipz.png

剩下的我也还在参透,
总之就是用了 super(props) 才能在下面语法使用 this ~

为什麽还要 bind 啊?

来到最後一个世纪谜题(?)

this.changeWeather = this.changeWeather.bind(this);

就是为什麽 this.changeWeather 还要 bind(this)

这边就直接把 bind 那一行程序注解掉再执行看看会发生什麽事吧!
https://ithelp.ithome.com.tw/upload/images/20210924/20129873N1eew7XOfQ.png

可以发现直接出错,错误讯息是

Cannot read properties of undefined (reading 'state')

哦,好像大概知道了,
weather 这个 state 被宣告在 constructor 里面,
在 constructor 外面的 changeWeather() 是不认得 this.state.weather 的,

this.changeWeather = this.changeWeather.bind(this);

所以这边有点是要建立 this.changeWeather 跟 constructor 里面 state 的桥梁的感觉(?)
这边看了几篇文章觉得还是没有参得很透,
我目前是先这样想啦XD

可以参考的文章们:
React 与 bind this 的一些心得
Handling Events(官方文件)

参考官方文件说:

// This binding is necessary to make this work in the callback
this.handleClick = this.handleClick.bind(this);

但我还是参不透XD

总之这篇文章大大有提到,

而当有了 Hooks 後,我们甚至不需要 super 或是 this。

XD
而之前学的 useState useEffect 好像都是 Hook 的一种XD
在官方文件 使用 State Hook 中,
提到:

Hook 是 React 16.8 中增加的新功能。它让你不必写 class 就能使用 state 以及其他 React 的功能。

哦~这也就难怪我之前写的语法貌似比较简单XD
所以我决定放弃研究 constructor super bind this
好啦,我觉得大概知道它用法就好,
至少之後在网路上看范例时知道它是做什麽的就好XD

不然我记得我之前在范例程序只要一看到以下这段我就会立马把那个页面关掉XD
至少现在我能面对它了(?)

constructor(props) {
    super(props);
    this.state = { weather: "sunny" };
    this.changeWeather = this.changeWeather.bind(this);
  }

然後一样附上今日程序→ Day22 - this.state & this.setState(Codecademy)

後记

看了一下 Codecademy,
後面要进入 React LifeCycle (生命周期) 了耶XD
希望看了之後可以参透今天不懂的这些地方XD


<<:  [Day 09] 建立机器学习模型 — Andrew Ng 大神说要这样做

>>:  认识HTML(七):表单栏位(上)

组策略和登录档监控--gpedit.msc及Process Monitor

今天预计要来介绍两支程序,让编辑登录档稍微安全的组策略编辑器(gpedit.msc)跟监控系统大小变...

【设计+切版30天实作】|Day18 - Bootstrap的客制化

大纲 上一篇把环境都建立完成後,今天要来做客制化,但在这之前,先来说明一下为什麽要客制化,以及为什麽...

Day07 Kibana - Query DSL 语法结构

上一篇我们已经学会了使用kibana来查询Elasticsearch资料,但有时候这种简单预设的查询...

Day 25 - Spring Security (二) UserDetailsService

Spring Security 的验证作业实际是交由``AuthenticationProvider...

Day2:How to use comments,octothorpe and variable in Python

Comment is a very important part in programing Com...