ReactJS - 使用 useState
useState 是一个基本的 React hook,它允许函数组件维护自己的状态并根据状态变化重新渲染自身。 useState 的签名如下 −
const [ <state>, <setState> ] = useState( <initialValue> )
其中,
initialValue − 状态的初始值。 state 可以指定为任何类型(数字、字符串、数组和对象)。
state − 表示状态值的变量。
setState −函数变量,表示更新 useState 返回的状态的函数。
setState 函数的签名如下 −
setState( <valueToBeUpdated> )
其中,valueToBeUpdated 是状态需要更新的值。设置和更新用户姓名的示例用法如下 −
// 初始化状态 const [name, setName] = useState('John') // 更新状态 setName('Peter)
功能
useState 的显著功能如下 −
函数参数 − 它接受一个函数(返回初始状态)而不是初始值,并且在组件的初始渲染期间仅执行一次该函数。如果初始值的计算成本很高,这将有助于提高性能。
const [val, setVal] = useState(() => { var initialValue = null // 初始值的计算成本高昂 return initialValue })
验证先前的值 − 它检查状态的当前值和先前值,只有当它们不同时,React 才会渲染其子项并触发效果。这将提高渲染的性能。
// ... setName('John') // 更新状态并重新渲染组件 // ... // ... setName('John') // 不会触发子项的渲染,因为状态的值没有改变。 // ...
批量更新多个状态 − React 在内部批量处理多个状态更新。如果需要立即更新多个状态,则可以使用 React 提供的特殊函数 flushSync,该函数将立即刷新所有状态更改。
flushSync(() => setName('Peter'))
应用状态Hooks(钩子)
让我们创建一个登录表单组件,并使用 useState Hooks(钩子)维护表单的值。
首先,使用以下命令创建并启动 React 应用程序,
create-react-app myapp cd myapp npm start
接下来,在组件文件夹 (src/components/LoginForm.js) 下创建一个 React 组件 LoginForm
import { useState } from 'react'; export default function LoginForm() { // 渲染代码 }
接下来,使用 useState Hooks(钩子)创建两个状态变量,用户名和密码,如下所示 −
import { useState } from 'react'; export default function LoginForm() { const [username, setUsername] = useState('') const [password, setPassword] = useState('') // 渲染代码 }
接下来,创建一个函数来验证登录数据,如下所示−
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使用了validate函数来验证并显示用户输入的数据。
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' })
在 hooks 中,setData(useState 返回的函数)将更新整个对象,如下所示 −
// 创建状态 const [data, setDate] = useState({ username: 'John', password: 'secret' }) // 更新状态 - 错误 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> ) }
此处,
State 在对象 (data) 中维护。
setData 由 useState Hooks(钩子)返回并用作状态更新函数。
data.* 语法用于获取状态的详细信息。
…data 扩展运算符与 setData 函数一起使用以更新状态。
摘要
useState Hooks(钩子)是一种在函数组件中进行状态管理的简单易行的方法。useState 可用于处理状态中的单个值或多个值。它支持基本数据类型和复杂对象。它允许多个状态设置函数 (set*) 和内部批处理以简化流程。由于引入了 useState Hooks(钩子),函数组件最终被改进为可以执行任何功能(从无状态到有状态)。