useState的基本用法
useState用於向函數組件添加狀態
它接收一個參數作為狀態的初始值,並返回一個數組
數組的第一個值為狀態,第二個值為改變狀態的函數
import React, { useState } from 'react'
function stateClass(){
const [name, setName] = useState('hong')
return (
<div>
<div>hello,{name}</div>
<button onClick={() => {setName('nihao')}}>點擊</button>
</div>
)
}
export default stateClass
在組件中讀狀態:直接訪問狀態名即可
在組件中修改狀態:調用函數,傳入狀態改變后的值
useEffect的基本用法
useEffect的作用是:添加組件已掛載的信號,並執行(和清理)副作用
它可以接收2個參數:回調函數、數組
1、只接收第一個參數:
當componentDidMount的時候,執行回調函數
當useState聲明的狀態被更新(視圖重新渲染)后,也執行回調函數
2、接收2個參數:“effect依賴於某一些state”
數組中寫的是用useState定義的狀態名稱
只有當數組中的狀態發生更新時,才執行回調函數
如果我們希望回調函數只在componentDidMount的時候執行一次,就可以寫一個空的數組(稱為“跳過effect")
3、回調函數的返回值
useEffect的回調函數允許返回一個函數,用來清理副作用
默認情況下(useEffect不寫第二個參數),只會在組件卸載(componentWillUnmount)的時候執行這個返回的函數
如果useEffect多次執行,在調用一個新的effect之前會對前一個effect進行清理
例子:我們想要訂閱this.props.friend.id的變化:
useEffect(() => {
// ...
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
可能產生的動作序列如下:
// Mount with { friend: { id: 100 } } props
ChatAPI.subscribeToFriendStatus(100, handleStatusChange); // 運行第一個 effect
// Update with { friend: { id: 200 } } props
ChatAPI.unsubscribeFromFriendStatus(100, handleStatusChange); // 清除上一個 effect
ChatAPI.subscribeToFriendStatus(200, handleStatusChange); // 運行下一個 effect
// Update with { friend: { id: 300 } } props
ChatAPI.unsubscribeFromFriendStatus(200, handleStatusChange); // 清除上一個 effect
ChatAPI.subscribeToFriendStatus(300, handleStatusChange); // 運行下一個 effect
// Unmount
ChatAPI.unsubscribeFromFriendStatus(300, handleStatusChange); // 清除最后一個 effect
需求分析
- 動態地、實時地顯示倒計時的時間
- 倒計時結束后,自動跳轉到另外一個頁面
代碼實現
首先我們需要一個counter狀態,表示 正在倒數的時間
還有一個timerID狀態,用來保存計時器的ID
其次,當頁面掛載完成的時候,需要創建一個計時器,待1s后執行count-1的操作
然后清理上一個計時器,並再次創建計時器,1s后執行count-1的操作...
我們可以利用useEffect的特性來實現這個功能:
const [timerID, setTimerID] = useState(null);
const [counter, setCounter] = useState(5);
useEffect(() => {
if(counter > 0){
let timer = setTimeout(() => {
setCounter(counter-1)
}, 1000);
setTimerID(timer)
}else{
props.history.push('/order')
}
return () => {
setTimerID(null)
}
},[counter]);
頁面掛載完成時:counter = 5,執行回調函數,保存計時器ID
1s后,執行計時器,count = 4
useEffect發現count更新,先清理副作用(setTimerID(null)),再新建計時器
1s后,執行計時器,count = 3
...如此循環直到count = 0 時,利用react-router做頁面的跳轉
完整代碼如下:
import React, {useState,useEffect} from 'react'
function Reminder(props) {
const [timerID, setTimerID] = useState(null);
const [counter, setCounter] = useState(5);
useEffect(() => {
if(counter > 0){
let timer = setTimeout(() => {
setCounter(counter-1)
}, 1000);
setTimerID(timer)
}else{
props.history.push('/order')
}
return () => {
setTimerID(null)
}
},[counter]);
return (
<div>
<p>{counter}秒后將自動跳轉至訂單頁面...</p>
</div>
);
}
export default Reminder