管理 React 元件的內部狀態

Jason Chung
前端魔法研究室
4 min readMar 22, 2016

在 React 的世界中,元件的資料來源有兩種方式:

  1. props:上層元件透過 props 傳遞資料給下層元件;props 就如同化學反應劑,當下層元件一接觸到,就立馬起了變化
  2. state:這一種類型的資料,是在元件內部進行定義的,通常會因為上層元件遞進來的 props 或是元件自身的行為而改變;而狀態的改變通常也會連鎖造成元件的變化

學習重點

本章節,我們將學習:

  1. 如何定義元件的初始狀態?
  2. 如何讀取元件的狀態?
  3. 如何更新元件的狀態?
  4. props 和 state 的差別是什麼?

今天的題目是

為了了解 state 的用法,我們試著實作看看簡單,資料又會一直變化的計數器:

需求非常的簡單:畫面顯示數字,從 0 開始,每秒鐘疊加 1

第一步、建立 Counter 元件

我們先建立 Counter 元件,並且根據需求實作 render 方法:

如果你想根據後面的步驟,完成今天的題目,這裡有準備好的程式 — jsfiddle

第二步、定義元件初始狀態

我們知道這一個 Counter 元件中的值是會根據時間每秒疊加 1 的。

因此像這樣元件內部資料的變化,我們會考慮用 state 來進行管理,下方是定義初始 state 的方法和讀取 state 的方法:

  1. 我們在 constuctor 中使用 this.state 定義初始狀態。
  2. constuctor 是一開始建立這個 class 實例時,會呼叫的 method;例如:new Counter()。
  3. 在 render 方法中,我們要顯示 state 中的值,因此可以直接從 this.state.value 獲得值。

第三步、更新狀態

上面那一個步驟,我們會一直顯示初始的狀態值:0。

現在我來先來看看怎麼改變 state 中的值:

  1. 我們建立一個方法:_increase,它的職責是將 state 中的 value 疊加 1,當往後每秒鐘我們都可以呼叫該方法來達到每秒 +1 的需求。
    備註:_increase 的名稱前有 _,只是因為我們想要分辨哪些是我們自己定義的方法,沒有特別強制。
  2. 在 _increase 中,我們呼叫 this.setState() 給予新的狀態值。
    這裡非常需要注意的是:你不能用 this.state = {} 給新值,因為 this.setState 的 API 也包含了要求 React 重新渲染元件,render 方法才會重新呼叫一次!

第四步、加入計時器

再來我們就要完成每秒都呼叫 _increase 的邏輯了:

  1. 這裡直接用到 setTimeout 方法,讓它每一秒(1000 ms)都呼叫一次 this._increase。
  2. 你可以看到遞的參數是 this._increase.bind(this),這是因為如果你沒有綁定 this,直接將 this._increase 遞給 setTimeout,當過了一秒後,_increase 被呼叫時會不知道該方法中的 this 是什麼,因此跑到 this.setState 就會出錯了!
    備註:這是 JS 的特性,更詳細的可以看這裡,我認為你要了解 .bind 的功用,也可以比較 .bind 和 .call 的差別。

重點整理

本章節的重點在第二步和第三步,也就是

  1. 在元件的 constructor 中,使用 this.state = {} 定義初始狀態
  2. 要讀取元件的狀態,可以直接用 this.state 來讀取
  3. 如果要更新元件狀態,務必呼叫 this.setState 這個 API 來改變

另外,你也必須了解元件的兩種資料來源,props 和 state 的差別:

  1. props 用在上層元件遞資料給下層元件
  2. state 用在管理元件內部資料

通常,我們會建議你應該設計無狀態(stateless)的元件,盡量讓下層的元件都可以通過 props 來得到資料。

這樣的好處是讓元件可以更容易重複使用,資料都由上層元件來管理,下層元件只需要負責接收資料和隨著資料做相對應的渲染。

下集預告

下一集,「使用 React 的表單元件」,盡情期待囉。

你應該會想看的

上一篇系列文章

--

--