useState 是 hook 的函數,它接收的參數是狀態的初始值(initial state),它會返回一個 Array,第0位是當前的 State 的值,第1位是可以改變 State 的 function
檔案位置 src/Example.js:
import React, { useState } from 'react';
function Example() {
const [ name, setName ] = useState('rainbow') // 初始值
const [ sex, setSex ] = useState('女') // 初始值
const [ age, setAge ] = useState(0) // 初始值
return (
<div>
<p>姓名:{name}</p>
<p>性別:{sex}</p>
<p>年紀:{age}(不可以點超過24下哈哈)</p>
<button onClick={()=>{setAge(age+1)}}>增加年紀</button>
</div>
)
}
export default Example;
上方這個例子,我們會拆解為 宣告、讀取、修改這三方面來說明:
1.先使用 const [ parameter, setParameter ] = useState('ParameterValue')
去宣告狀態。
這裡要注意這方法是 ES6 中的解構賦值,如果不寫成解構賦值要改寫成:
let _useState = useState(0)
let parameter = _useState[0]
let setParameter = _useState[1]
2.再來在 return 後運用 {paramter}
來讀取該 State 的值
3.最後使用{()=>{setParameter(parameterNewValue)}}
搭配事件去修改 paramter 的值,關於 setParameter,它所接收的是將要更新的值,然後就交給 React 去進行重新渲染
react 會等到 render 完後才去調用 useEffect,所以可以讓我們在函數元件中執行副作用的操作,可以把 useEffect 看作 ComponentDidMount、ComponentDidUpdate、ComponentWillUnMount的綜合體
這裏的副作用(Side Effect)指的是我們需要額外功能來取得或處理資料,像是 fetchData, eventHandling,之前有說一般都會在 ComponentDidMount 時處理
回調函數返回函數,相當於 ComponentWillUnmount
// 在回調函數返回一個函數,則是用於清理,像是 ComponentWillUnmount
useEffect(() => {
// componentDidMount, componentDidUpdate 在這裡執行
console.log('進入頁面')
return () => {
// componentWillUnmount 在這裡執行
console.log('離開了')
}
},[])
// 對應到 React Class Component用法:
componentDidMount() {
console.log('進入頁面')
}
componentWillUnmount() {
console.log('離開了')
}
回調函數裡進行副作用操作(像是請求資料),React 官方推薦在 componentDidMount 裡處理
// 在回調函數裡請求資料:
useEffect(() => {
const fetchData = async() => {
await fetch('data url').then(res => res.json())
}
}, [])
// 對應到 React Class Component用法:
componentDidMount() {
const fetchData = async() => {
await fetch('data url').then(res => res.json())
}
}
如果沒有帶入 Array,則每一次更新後都會執行:
// 它在第一次渲染後每次更新都會執行:
useEffect(() => {
console.log(`你已經點擊了 ${count} 次`)
})
// 對應到 React Class Component用法:
componentDidMount() {
console.log(`你已經點擊了 ${count} 次`)
}
componentDidUpdate() {
console.log(`你已經點擊了 ${count} 次`)
}
如果帶入[],則只在初次 render 後執行一次:
// 它只在第一次 render 後執行一次:
useEffect(() => {
console.log(`你已經點擊了 ${count} 次`)
},[])
// 對應到 React Class Component用法:
componentDidMount() {
console.log(`你已經點擊了 ${count} 次`)
}
如果帶入[parameter],則在 parameter 發生改變後執行:
// 它只在 state 數據發生改變後執行 Effect
useEffect(() => {
console.log(`你已經點擊了 ${count} 次`)
}, [count]) // 只在 count 發生變化後執行
// 對應到 React Class Component用法:
componentDidUpdate(prevProps, prevState) {
if (prevState.count !== this.state.count) {
console.log(`你已經點擊了 ${count} 次`)
}
}
接下來搭配我們前幾天講的 react-router-dom 來實作看看計數器功能。
檔案位置 src/Example.js:
import React, { useState, useEffect } from 'react';
import { BrowserRouter , Route, Link } from 'react-router-dom';
function Index() {
useEffect(() => {
// componentDidMount, componentDidUpdate 在這裡執行
console.log('useEffect=> Index頁面')
return () => {
// componentWillUnmount 在這裡執行
console.log('離開Index頁面')
}
}, [])
// 可以試著拿掉 []--------------(1)
// 會發現每次 點擊增加按鈕 都會執行 'useEffect=> Index頁面' 與 '離開Index頁面'
return <h2>Rainbow Web</h2>
}
function SecondPage() {
useEffect(() => {
console.log('useEffect=> Second頁面')
return () => {
console.log('離開Second頁面')
}
}, [])
// 可以試著拿掉 []--------------(2)
// 會發現每次 點擊增加按鈕 都會執行 'useEffect=> Second頁面' 與 '離開Second頁面'
return <h2>Rainbow Sencond Page</h2>
}
function Example() {
const [count, setCount] = useState(0)
// 下方這個 useEffect 只在 count 發生變化時執行
// 可以試著將 [count] 改成 [] --------------(3)
// 會發現 useEffect 就只會在 render 完後執行一次
useEffect(() => {
console.log(`useEffect=> 已經點擊了${count}次數`)
return () => {
console.log('=========================')
}
},[count])
return (
<div>
<p>你已經點擊了{ count } 次數</p>
<button onClick={() => {setCount( count+1 )}}>增加</button>
<BrowserRouter>
<ul>
<li><Link to="/">首頁</Link></li>
<li><Link to="/secondPage/">第二分頁</Link></li>
</ul>
<Route path="/" exact component={Index} />
<Route path="/secondPage/" component={SecondPage} />
</BrowserRouter>
</div>
)
}
export default Example;
要開始燃燒了~衝刺