網站首頁 編程語言 正文
State Hook
這個例子用來顯示一個計數器。當你點擊按鈕,計數器的值就會增加:
import React, { useState } from 'react'; function Example() { // 聲明一個叫 “count” 的 state 變量。 const [count, setCount] = useState(0); return (); }You clicked {count} times
在這里,useState
?就是一個 Hook (等下我們會講到這是什么意思)。通過在函數組件里調用它來給組件添加一些內部?state
。React 會在重復渲染時保留這個?state
。useState
?會返回一對值:當前狀態和一個讓你更新它的函數,你可以在事件處理函數中或其他一些地方調用這個函數。它類似?class
?組件的?this.setState
,但是它不會把新的?state
?和舊的?state
?進行合并。(我們會在使用 State Hook 里展示一個對比?useState
?和?this.state
?的例子)。
useState
?唯一的參數就是初始?state
。在上面的例子中,我們的計數器是從零開始的,所以初始?state
?就是?0
。值得注意的是,不同于?this.state
,這里的?state
?不一定要是一個對象 —— 如果你有需要,它也可以是。這個初始?state
?參數只有在第一次渲染時會被用到。
聲明多個 state 變量
你可以在一個組件中多次使用 State Hook:
function ExampleWithManyStates() { // 聲明多個 state 變量! const [age, setAge] = useState(42); const [fruit, setFruit] = useState('banana'); const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]); // ... }
數組解構的語法讓我們在調用?useState
?時可以給?state
?變量取不同的名字。當然,這些名字并不是?useState
?API 的一部分。React 假設當你多次調用?useState
?的時候,你能保證每次渲染時它們的調用順序是不變的。后面我們會再次解釋它是如何工作的以及在什么場景下使用。
那么,什么是 Hook?
Hook 是一些可以讓你在函數組件里 " 鉤入" React?state
?及生命周期等特性的函數。Hook 不能在?class
?組件中使用 —— 這使得你不使用?class
?也能使用 React。(我們不推薦把你已有的組件全部重寫,但是你可以在新組件里開始使用 Hook。)
React 內置了一些像?useState
?這樣的 Hook。你也可以創建你自己的 Hook 來復用不同組件之間的狀態邏輯。我們會先介紹這些內置的 Hook。
Effect Hook
你之前可能已經在 React 組件中執行過數據獲取、訂閱或者手動修改過 DOM。我們統一把這些操作稱為“副作用”,或者簡稱為“作用”。
useEffect
?就是一個 Effect Hook,給函數組件增加了操作副作用的能力。它跟?class
?組件中的?componentDidMount
、componentDidUpdate
?和?componentWillUnmount
?具有相同的用途,只不過被合并成了一個 API。
例如,下面這個組件在 React 更新 DOM 后會設置一個頁面標題:
import React, { useState, useEffect } from 'react'; function Example() { const [count, setCount] = useState(0); // 相當于 componentDidMount 和 componentDidUpdate: useEffect(() => { // 使用瀏覽器的 API 更新頁面標題 document.title = `You clicked ${count} times`; }); return (); }You clicked {count} times
當你調用?useEffect
?時,就是在告訴 React 在完成對 DOM 的更改后運行你的“副作用”函數。由于副作用函數是在組件內聲明的,所以它們可以訪問到組件的?props
?和?state
。默認情況下,React 會在每次渲染后調用副作用函數 ——?包括第一次渲染的時候。
副作用函數還可以通過返回一個函數來指定如何“清除”副作用。例如,在下面的組件中使用副作用函數來訂閱好友的在線狀態,并通過取消訂閱來進行清除操作:
import React, { useState, useEffect } from 'react'; function FriendStatus(props) { const [isOnline, setIsOnline] = useState(null); function handleStatusChange(status) { setIsOnline(status.isOnline); } useEffect(() => { ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange); return () => { ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange); }; }); if (isOnline === null) { return 'Loading...'; } return isOnline ? 'Online' : 'Offline'; }
在這個示例中,React 會在組件銷毀時取消對?ChatAPI
?的訂閱,然后在后續渲染時重新執行副作用函數。(如果傳給?ChatAPI
?的?props.friend.id
?沒有變化,你也可以告訴 React 跳過重新訂閱。)
跟?useState
?一樣,你可以在組件中多次使用?useEffect
?:
function FriendStatusWithCounter(props) { const [count, setCount] = useState(0); useEffect(() => { document.title = `You clicked ${count} times`; }); const [isOnline, setIsOnline] = useState(null); useEffect(() => { ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange); return () => { ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange); }; }); function handleStatusChange(status) { setIsOnline(status.isOnline); } // ...
通過使用 Hook,你可以把組件內相關的副作用組織在一起(例如創建訂閱及取消訂閱),而不要把它們拆分到不同的生命周期函數里。
Hook 使用規則
Hook 就是 JavaScript 函數,但是使用它們會有兩個額外的規則:
- 只能在函數最外層調用 Hook。不要在循環、條件判斷或者子函數中調用。
- 只能在?React 的函數組件中調用 Hook。不要在其他 JavaScript 函數中調用。(還有一個地方可以調用 Hook —— 就是自定義的 Hook 中,我們稍后會學習到。)
自定義 Hook
有時候我們會想要在組件之間重用一些狀態邏輯。目前為止,有兩種主流方案來解決這個問題:高階組件和?render props
。自定義 Hook 可以讓你在不增加組件的情況下達到同樣的目的。
前面,我們介紹了一個叫?FriendStatus
?的組件,它通過調用?useState
?和?useEffect
?的 Hook 來訂閱一個好友的在線狀態。假設我們想在另一個組件里重用這個訂閱邏輯。
首先,我們把這個邏輯抽取到一個叫做?useFriendStatus
?的自定義 Hook 里:
import React, { useState, useEffect } from 'react'; function useFriendStatus(friendID) { const [isOnline, setIsOnline] = useState(null); function handleStatusChange(status) { setIsOnline(status.isOnline); } useEffect(() => { ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange); return () => { ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange); }; }); return isOnline; }
它將?friendID
?作為參數,并返回該好友是否在線:
現在我們可以在兩個組件中使用它:
function FriendStatus(props) { const isOnline = useFriendStatus(props.friend.id); if (isOnline === null) { return 'Loading...'; } return isOnline ? 'Online' : 'Offline'; }
function FriendListItem(props) { const isOnline = useFriendStatus(props.friend.id); return (
每個組件間的?state
?是完全獨立的。Hook 是一種復用狀態邏輯的方式,它不復用?state
?本身。事實上 Hook 的每次調用都有一個完全獨立的?state
?—— 因此你可以在單個組件中多次調用同一個自定義 Hook。
自定義 Hook 更像是一種約定而不是功能。如果函數的名字以?use
?開頭并調用其他 Hook,我們就說這是一個自定義 Hook。?useSomething
?的命名約定可以讓我們的?linter
?插件在使用 Hook 的代碼中找到 bug。
你可以創建涵蓋各種場景的自定義 Hook,如表單處理、動畫、訂閱聲明、計時器,甚至可能還有更多我們沒想到的場景。我們很期待看到 React 社區會出現什么樣的自定義 Hook。
其他 Hook
除此之外,還有一些使用頻率較低的但是很有用的 Hook。比如,useContext
?讓你不使用組件嵌套就可以訂閱 React 的 Context。
function Example() { const locale = useContext(LocaleContext); const theme = useContext(ThemeContext); // ... }
另外?useReducer
?可以讓你通過?reducer
?來管理組件本地的復雜?state
。
function Todos() { const [todos, dispatch] = useReducer(todosReducer); // ...
總結
原文鏈接:https://blog.csdn.net/weixin_44491423/article/details/123506737
相關推薦
- 2022-10-25 Android自定義View實現水波紋擴散效果_Android
- 2023-11-17 python中numpy ndarray 按條件篩選數組,關聯篩選的例子——numpyarray對數
- 2022-09-03 golang?四則運算計算器yacc歸約手寫實現_Golang
- 2022-04-24 C語言的隨機數rand()函數詳解_C 語言
- 2022-06-29 python中py文件與pyc文件相互轉換的方法實例_python
- 2022-05-24 調用無文檔說明的?Web?API過程描述_相關技巧
- 2022-04-20 C#9.0推出的4個新特性介紹_C#教程
- 2022-10-21 一文詳解?Compose?Navigation?的實現原理_Android
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支