
- ReactJS 教程
- ReactJS - 首頁
- ReactJS - 簡介
- ReactJS - 路線圖
- ReactJS - 安裝
- ReactJS - 特性
- ReactJS - 優點與缺點
- ReactJS - 架構
- ReactJS - 建立 React 應用
- ReactJS - JSX
- ReactJS - 元件
- ReactJS - 巢狀元件
- ReactJS - 使用新建立的元件
- ReactJS - 元件集合
- ReactJS - 樣式
- ReactJS - 屬性 (props)
- ReactJS - 使用屬性建立元件
- ReactJS - props 驗證
- ReactJS - 建構函式
- ReactJS - 元件生命週期
- ReactJS - 事件管理
- ReactJS - 建立事件感知元件
- ReactJS - 在 Expense Manager 應用中引入事件
- ReactJS - 狀態管理
- ReactJS - 狀態管理 API
- ReactJS - 無狀態元件
- ReactJS - 使用 React Hooks 進行狀態管理
- ReactJS - 使用 React Hooks 進行元件生命週期管理
- ReactJS - 佈局元件
- ReactJS - 分頁
- ReactJS - Material UI
- ReactJS - Http 客戶端程式設計
- ReactJS - 表單程式設計
- ReactJS - 受控元件
- ReactJS - 非受控元件
- ReactJS - Formik
- ReactJS - 條件渲染
- ReactJS - 列表
- ReactJS - Keys
- ReactJS - 路由
- ReactJS - Redux
- ReactJS - 動畫
- ReactJS - Bootstrap
- ReactJS - 地圖
- ReactJS - 表格
- ReactJS - 使用 Flux 管理狀態
- ReactJS - 測試
- ReactJS - CLI 命令
- ReactJS - 構建和部署
- ReactJS - 示例
- Hooks
- ReactJS - Hooks 簡介
- ReactJS - 使用 useState
- ReactJS - 使用 useEffect
- ReactJS - 使用 useContext
- ReactJS - 使用 useRef
- ReactJS - 使用 useReducer
- ReactJS - 使用 useCallback
- ReactJS - 使用 useMemo
- ReactJS - 自定義 Hooks
- ReactJS 高階
- ReactJS - 可訪問性
- ReactJS - 程式碼分割
- ReactJS - 上下文
- ReactJS - 錯誤邊界
- ReactJS - 轉發 Refs
- ReactJS - 碎片
- ReactJS - 高階元件
- ReactJS - 與其他庫整合
- ReactJS - 最佳化效能
- ReactJS - Profiler API
- ReactJS - 傳送門
- ReactJS - 無 ES6 ECMAScript 的 React
- ReactJS - 無 JSX 的 React
- ReactJS - 調和
- ReactJS - Refs 和 DOM
- ReactJS - 渲染 Props
- ReactJS - 靜態型別檢查
- ReactJS - 嚴格模式
- ReactJS - Web Components
- 其他概念
- ReactJS - 日期選擇器
- ReactJS - Helmet
- ReactJS - 內聯樣式
- ReactJS - PropTypes
- ReactJS - BrowserRouter
- ReactJS - DOM
- ReactJS - 輪播圖
- ReactJS - 圖示
- ReactJS - 表單元件
- ReactJS - 參考 API
- ReactJS 有用資源
- ReactJS - 快速指南
- ReactJS - 有用資源
- ReactJS - 討論
ReactJS - 使用 useState
useState 是一個基本的 React Hook,它允許函式元件維護自己的狀態,並根據狀態變化重新渲染自身。useState 的簽名如下:
const [ <state>, <setState> ] = useState( <initialValue> )
其中,
initialValue - 狀態的初始值。狀態可以指定為任何型別(數字、字串、陣列和物件)。
state - 用於表示狀態值的變數。
setState - 函式變數,用於表示由 useState 返回的更新狀態的函式。
setState 函式的簽名如下:
setState( <valueToBeUpdated> )
其中,valueToBeUpdated 是要更新的狀態的值。設定和更新使用者名稱稱的示例用法如下:
// initialize the state const [name, setName] = useState('John') // update the state setName('Peter)
特性
useState 的顯著特性如下:
函式引數 - 它接受一個函式(返回初始狀態)而不是初始值,並且只在元件的初始渲染期間執行一次該函式。如果初始值的計算代價很高,這將有助於提高效能。
const [val, setVal] = useState(() => { var initialValue = null // expensive calculation of initial value return initialValue })
驗證先前值 - 它檢查狀態的當前值和先前值,並且只有當它們不同時,React 才會渲染其子元素並觸發效果。這將提高渲染效能。
// ... setName('John') // update the state and rerender the component // ... // ... setName('John') // does not fire the rendering of the children because the value of the state have not changed. // ...
批次更新多個狀態 - React 在內部批次處理多個狀態更新。如果必須立即進行多個狀態更新,則可以使用 React 提供的特殊函式 flushSync,它將立即重新整理所有狀態更改。
flushSync(() => setName('Peter'))
應用狀態 Hook
讓我們建立一個登入表單元件,並使用 useState Hook 維護表單的值。
首先,使用以下命令建立並啟動一個 React 應用:
create-react-app myapp cd myapp npm start
接下來,在元件資料夾下建立一個 React 元件 LoginForm (src/components/LoginForm.js)
import { useState } from 'react'; export default function LoginForm() { // render code }
接下來,使用 useState Hook 建立兩個狀態變數 username 和 password,如下所示:
import { useState } from 'react'; export default function LoginForm() { const [username, setUsername] = useState('') const [password, setPassword] = useState('') // render code }
接下來,建立一個函式來驗證登入資料,如下所示:
import { useState } from 'react'; export default function LoginForm() { const [username, setUsername] = useState('') const [password, setPassword] = useState('') let isEmpty = (val) => { if(val == null || val == '') { return true; } else { return false; } } let validate = (e) => { e.preventDefault() if(!isEmpty(username) && !isEmpty(password)) { alert(JSON.stringify({ username: username, password: password })) } else { alert("Please enter username / password") } } // render code }
這裡,isEmpty 是一個函式,用於檢查資料是否存在或為空。
接下來,渲染一個帶有兩個輸入欄位的登入表單,並使用狀態變數 (username 和 password)、狀態更新方法 (setUsername 和 setPassword) 和驗證方法來處理表單。
import { useState } from 'react'; export default function LoginForm() { return ( <div style={{ textAlign: "center", padding: "5px" }}> <form name="loginForm"> <label for="username">Username: </label> <input id="username" name="username" type="text" value={username} onChange={(e) => setUsername(e.target.value)} /> <br /> <label for="password">Password: </label> <input id="password" name="password" type="password" value={password} onChange={(e) => setPassword(e.target.value)} /> <br /> <button type="submit" onClick={(e) => validate(e)}>Submit</button> </form> </div> ) }
這裡,
onChange 使用 Hook 返回的狀態設定函式。
onClick 使用驗證函式來驗證並顯示使用者輸入的資料。
LoginForm 元件的完整程式碼如下:
import { useState } from 'react'; export default function LoginForm() { const [username, setUsername] = useState('') const [password, setPassword] = useState('') let isEmpty = (val) => { if(val == null || val == '') { return true; } else { return false; } } let validate = (e) => { e.preventDefault() if(!isEmpty(username) && !isEmpty(password)) { alert(JSON.stringify({ username: username, password: password })) } else { alert("Please enter username / password") } } return ( <div style={{ textAlign: "center", padding: "5px" }}> <form name="loginForm"> <label for="username">Username: </label> <input id="username" name="username" type="text" value={username} onChange={(e) => setUsername(e.target.value)} /> <br /> <label for="password">Password: </label> <input id="password" name="password" type="password" value={password} onChange={(e) => setPassword(e.target.value)} /> <br /> <button type="submit" onClick={(e) => validate(e)}>Submit</button> </form> </div> ) }
接下來,更新根應用程式元件 App.js,如下所示:
import './App.css'; import HelloWorld from './components/HelloWorld'; import LoginForm from './components/LoginForm'; function App() { return ( <LoginForm /> ); } export default App;
接下來,開啟瀏覽器並檢查應用程式。應用程式將使用狀態變數收集使用者輸入的資料,並使用驗證函式對其進行驗證。如果使用者輸入了正確的資料,它將顯示資料,如下所示:

否則,它將丟擲錯誤,如下所示:

物件作為狀態
在基於類的狀態管理中,setState 方法支援狀態物件的區域性更新。例如,讓我們考慮一下登入表單資料作為物件儲存在狀態中。

{ username: 'John', password: 'secret' }
使用 setState 更新使用者名稱只會更新狀態物件中的使用者名稱並保留密碼欄位。
this.setState({ username: 'Peter' })
在 Hook 中,setData(由 useState 返回的函式)將更新整個物件,如下所示:
// create state const [data, setDate] = useState({ username: 'John', password: 'secret' }) // update state - wrong setData({ username: 'Peter' })
更新後的狀態沒有密碼欄位,如下所示:
{ username: 'Peter' }
為了解決這個問題,我們可以使用 JavaScript 中的擴充套件運算子,如下所示:
setData({ ...data, username: 'Peter' })
讓我們透過轉換 LoginForm 元件建立一個新元件,並使用物件狀態變數,如下所示:
import { useState } from 'react'; export default function LoginFormObject() { const [data, setData] = useState({}) let isEmpty = (val) => { if(val == null || val == '') { return true; } else { return false; } } let validate = (e) => { e.preventDefault() if(!isEmpty(data.username) && !isEmpty(data.password)) { alert(JSON.stringify(data)) } else { alert("Please enter username / password") } } return ( <div style={{ textAlign: "center", padding: "5px" }}> <form name="loginForm"> <label for="username">Username: </label> <input id="username" name="username" type="text" value={data.username} onChange={(e) => setData( {...data, username: e.target.value} )} /> <br /> <label for="password">Password: </label> <input id="password" name="password" type="password" value={data.password} onChange={(e) => setData({...data, password: e.target.value})} /> <br /> <button type="submit" onClick={(e) => validate(e)}>Submit</button> </form> </div> ) }
這裡,
狀態 儲存在物件 (data) 中。
setData 由 useState Hook 返回,並用作狀態更新函式。
data.* 語法用於獲取狀態的詳細資訊。
...data 擴充套件運算子與 setData 函式一起使用來更新狀態。
總結
useState Hook 是一種在函式元件中進行狀態管理的簡單易行的方法。useState 可用於處理狀態中的單個值或多個值。它支援基本資料型別和複雜物件。它允許使用多個狀態設定函式 (set*) 並在內部進行批處理以簡化流程。由於引入了 useState Hook,函式元件最終得到了改進,可以執行任何功能(從無狀態到有狀態)。