昨天我們學習了props和event handler來幫component增加更多變化,但是,只用props和event handler沒辦法讓component隨著使用者的動作改變內容,充其量只是把變數放進去、偵測到動作的發生而已。若要讓內容隨著使用者的動作變化,hooks是必不可少的。
今天我先來介紹一下最基本、也是最容易使用到的hook,useState
,來看看要怎麼讓網站內容變化吧!
到目前為止,我們寫的程式都是靜態的,如果要讓它動起來怎麼辦呢?例如,設計一個計數器,使用者每按一次按鈕,次數就+1,若是照以往寫JS的經驗,很容易會想到以下寫法:
const App = () => {
let count = 0;
const handleClick = (e) => {
count++;
}
return (
<div>
<div style={{fontSize: "3rem", textAlign: "center", width: "100px"}}> {count} </div>
<button onClick={handleClick}>加1</button>
</div>
)
}
然而,這樣執行後會發現,完全沒有變化!顯示的數字仍然掛蛋,沒有加1。
由於count
只是單純的變數,React在讀取時只會讀取到最初執行的那一次並render出來,後續數字改變並不會被React偵測到並render出來。
因此,必須要在count
上掛上"掛勾",讓React可以偵測到變數的變化,並重新render網頁,這個掛上掛鉤的方法就是使用useState
,讓變數與這個Component勾起來。useState
是React中的一個method,因此得先引入它:
import {useState} from 'react';
接著就可以在component中使用它了。要執行useState
,必須先傳入一個參數,當作變數的初始值。useState
會回傳一個Array,Array的第一個值是變數,也就相當於上面的count
;第二個值是改變這個變數要用的function。為了方便取用,一般會使用ES6陣列解構的方式去取值:
// 自useState中取出 count 及 setCount ,count 的初始值為0
const [count, setCount] = useState(0);
通常改變變數的function會取名叫做set,比較好記。
要使用setCount
,只需要在setCount中放入要改變的值就好了,相當方便。
接下來就可以把count和setCount放入剛剛的程式碼中了:
const App = () => {
// 改成useState
const [count, setCount] = useState(0);
const handleClick = (e) => {
setCount(count++);
}
return (
<div>
<div style={{fontSize: "3rem", textAlign: "center", width: "100px"}}> {count} </div>
<button onClick={handleClick}>加1</button>
</div>
)
}
這樣就成功了!
useState
回傳的變數部分,不可以直接修改,直接修改React不會知道你修改了state,所以必須使用setState方法。const [count, setCount] = useState(0);
const handleClick = (e) => {
setCount(count++);
console.log(count)
}
這樣的做法看起來沒什麼問題,但若是使用者點擊速度極快,在setState function還沒更新完成時,console.log
就會顯示出更新前的值。解方可以搭配之後會說到的useEffect
,偵測變化再執行console.log
。
3. 若更新的值與原先的state相同,React不會re-render
如果setState函式中傳入的跟目前state的值相同,則React不會重新渲染頁面。
4. 每一次re-render時,state初始值仍會跑一次
即使state被更新,React在更新component時仍會重新跑一次state的初始值。若是希望初始值在第一次render後就不再被執行,可以參考這篇提供的方法。
參考資料:
React官網
關於 useState,你需要知道的事