React.js快速入門 — (5)Prop&State&Hook
Prop&State&Hook — React.js如何存取資料,針對16.8版後的React.js所製作的新手入門上手文章
結束了Component重要的章節後,接下來第二重要的功能:Prop&State&Hook,也乘載了所有生命週期動態更新的責任。
還記得在第二章Overview的這張圖片。
所有事情只要產生改變一定會進入
render
。若有呈現到網頁,都一定會不斷刷新到網頁上。
其中一部分就是在”更新時”階段,只要React.js的資料有所改變,就一定會觸發 render
,針對網頁結構做出改變。
以下是對於資料流生命週期會使用到的函式:
所有生命週期的步驟請熟記,它會協助你哪個時期會發生的事情。在做Debug(偵錯)的時候,也能比較了解是哪個環節出錯。
接下來使用資料的類型去詮釋生命週期的觸發:
Prop
在前幾個章節我們都能看到 prop
的身影,因為它協助我們將資料傳入Component。最重要的是它是Read-Only(唯讀)不隨意被更改的,畢竟更改它沒有意義,也沒法回傳給上層。
傳遞方式
在JSX使用Attribute(屬性)方式傳遞下去,注意屬性建議使用camelCase命名。
const name = "Hello";
const element = <Hello myName={name} />
function Hello(props){
return <h1>Hello, my name is {props.myName}</h1>;
}
(ES6) Class Component綁定
在Class Component,必須先在Class的 constructor()
繼承 props
的屬性。日後在 render()
就可以直接用 this.props
呼叫傳進來的參數。
class Hello extends React.Component{
constructor(props){
super(props);
}
render(){
return <h1>Hello, my name is {this.props.myName}</h1>;
}
}
State
state
使用在(ES6) Class Component,必須在Class的 constructor()
先宣告好資料結構。它也跟 prop
一樣是Read-Only的,我們使用 {this.state.<arg>}
時只能做讀取。寫入的時候必須用React.js替它設計的 setState()
完成。
State有以下事情需要注意:
1. State 又稱 Local state,只有呼叫它的物件或是Component擁有才能使用。除非是有上層下指令才能使上層一起擁有。
2. 只要State一被修改,就一定會觸發 render()
更新頁面。
宣告
在 constructor()
用Javascript Dictionary型別宣告好資料結構
class Hello extends React.Component{
constructor(){
this.state = {name: ""};
}
}
設定資料
使用 setState()
完成檔案設定,括號裏頭使用Javascript Dictionary型式,不用將全部資料結構設定一遍。因為State是採用合併(merge)形式,它會找到相對應的欄位,並且做部分更新。
假設我們宣告以下結構:
class Hello extends React.Component{
constructor(){
this.state = {name: "", audience: 0};
}
}
我們只要下以下指令,它就會只更新 name
的部分,並不會影響到 audience
:
this.setState({name: "Hello"});
React 可以將多個
setState()
呼叫批次處理為單一的更新,以提高效能。
Function 將接收先前的 state 作為第一個參數,並且將更新的 props 作為第二個參數
它也可以用Arrow Function與 prop
做結合,成為一種非同步更新:
this.setState((state, props) => ({
counter: state.counter + props.increment
}));
結合生命週期
上面我們講了資料設定,但沒有提及要在哪邊設定!原因是 state
並不會在 render()
做設定 ,它要配合一些HTML表單同步或者是生命週期才會使用。在上方提及的生命週期圖片的 can use this.setState()
,或是HTML的監聽函式才能使用。
我們可以將那些提供的函式呼叫做Override(覆寫):
class Hello extends React.Component{
// ...
componentDidMount(){
this.setState(...);
}
// ...
}
Hook
Hook 是 function,他讓你可以從 function component「hook into」React state 與生命週期功能。
在16.8版後誕生的功能,是在Function Component也能使用(ES6) Class Component的State。React.js在文本也說道,Javascript最大魔王之一無非就是運用 this
的概念。在一般函式、Prototype、ES6 Class、匿名函式、箭頭函式每個區域的 this
用法都不太一樣,容易造成寫手迷失使用方向。加上(ES6) Class Component有點像是過度包裝,當有好多個Component會覺得很複雜。
因此官方建議少用Class Component多使用Hook於Function Component。不過 Class Component還是要有些基礎概念,畢竟現在很多寫好的工具都還是用其,必須要看得懂才能妥善運用。
使用
Hook 只有兩種函式可以使用: useState
跟 useEffect
。
useState :如同 state
般的方法,傳進去的就是想儲存的資料。它會回傳兩個變數,一個是目前state,如下方的 count
;另一則是更新state的函式,如下方的 setCount
。
function Counter({initialCount}) {
const [count, setCount] = useState(initialCount);
return (
<div>
<h1>Count: {count}</h1>
<button onClick={() => setCount(prevCount => prevCount + 1)}>+</button>
</div>
);
}
- 因為
useState
回傳的是兩個變數組成的陣列,所以我們在接收端也掛上中括號就可以直接取這兩個變數。 - onclick因為屬性問題需設定成一個函式之後,才能呼叫
setCount
。 setCount
會先回傳目前Statecount
,亦即裡面宣告的prevCount
。
useEffect:和 componentDidMount
,componentDidUpdate
,與 componentWillUnmount
有著同樣的宗旨,但整合進一個單一的 API。主要就是協助觸發除了更改 state
內容外任何想做的事。傳入的參數必須為一個函式,就可以開始做任何的事情。厲害的是,它可以不用到 this
的字眼,減少除錯的功夫。
useEffect(()=>{
// Do anything you want.
});
以上就介紹完 Hook所有基本的呼叫了!
注意
Hook 有兩件事情須注意:
1. 只能在 Function Component呼叫
2. 只能在 Function 最上層呼叫,所以for loop、if-else與Nested(巢狀) function都不能使用,這會影響到 useEffect
的使用,將在下方解釋。
function Top(){
// for loop
for(var i=0;...)
// if-else
if (){}else{}
// Nested function
function Sec(){}
const third = function(){}
}
React.js會去記住這個Component的Hook觸發順序,每一次的使用這函式的Hook必須是固定的。假如我們加上if-else在其中:
function sayMyName(){
const [name, setName] = useState('Mary');
if (name !== '') {
useEffect(function persistForm() {
// ...
});
}
}
會一下這次呼叫有 name的useState
跟 persistForm的useEffect
,可能下一次只剩 name的useState
。這會讓React.js不知道useEffect要怎麼去綁定。因此要使用if-else的方法就是放進去useEffect裏頭:
function sayMyName(){
const [name, setName] = useState('Mary');
useEffect(function persistForm() {
if (name !== '') {
// ...
}
// ...
});
}
這樣就能確保每一次都呼叫得到。
其他
React.js也提供可自行設定Hook。
題外話,若未來想做登入狀態這種全域資料存取,可以翻閱進階指南的Context;Hook部分則是有 useContext
。
結語
在此,整個React.js快速入門的系列文章就告一段落了。對React.js有了初步印象,就開始建議前往二刷官方文本(安裝加上主要概念章節),讓整個概念組織起來。若對內容有任何問題或是需修正的,也請在每個文章下方留言告訴我。謝謝您的觀看💪
喜歡的話可以給我一點掌聲唷!