- 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 APP中引入事件
- ReactJS - 状态管理
- ReactJS - 状态管理 API
- ReactJS - 无状态组件
- ReactJS - 使用 React Hooks 进行状态管理
- ReactJS - 使用 React 钩子的组件生命周期
- ReactJS - 组件的布局
- ReactJS - 分页
- ReactJS - Material 用户界面
- ReactJS - Http 客户端编程
- ReactJS - 表单编程
- ReactJS - 受控组件
- ReactJS - 不受控制的组件
- ReactJS - Formik
- ReactJS - 条件渲染
- ReactJS - 列表
- ReactJS - 键
- ReactJS - 路由
- ReactJS - 冗余
- ReactJS - 动画
- ReactJS - 引导程序
- ReactJS - 地图
- ReactJS - 表格
- ReactJS - 使用 Flux 管理状态
- ReactJS - 测试
- ReactJS - CLI 命令
- ReactJS - 构建和部署
- ReactJS - 示例
- ReactJS - 钩子简介
- ReactJS - 使用 useState
- ReactJS - 使用 useEffect
- ReactJS - 使用 useContext
- ReactJS - 使用 useRef
- ReactJS - 使用 useReducer
- ReactJS - 使用 useCallback
- ReactJS - 使用 useMemo
- ReactJS - 自定义钩子
- ReactJS - 可访问性
- ReactJS - 代码拆分
- ReactJS - 上下文
- ReactJS - 错误边界
- ReactJS - 转发引用
- ReactJS - 片段
- ReactJS - 高阶组件
- ReactJS - 与其他库集成
- ReactJS - 优化性能
- ReactJS - 分析器 API
- ReactJS - 门户
- ReactJS - 没有 ES6 ECMAScript 的 React
- ReactJS - 没有 JSX 的 React
- ReactJS - 协调
- ReactJS - 引用和 DOM
- ReactJS - 渲染属性
- ReactJS - 静态类型检查
- ReactJS - 严格模式
- ReactJS - Web 组件
- ReactJS - 日期选择器
- ReactJS - Helmet
- ReactJS - 内联样式
- ReactJS - 属性类型
- ReactJS - 浏览器路由器
- ReactJS - DOM
- ReactJS - 旋转木马
- ReactJS - 图标
- ReactJS - 表单组件
- ReactJS - 参考 API
ReactJS - 使用 useState
useState 是一个基本的 React 钩子,它允许函数组件保持自己的状态,并根据状态变化重新渲染自身。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'))
应用状态钩子
让我们创建一个登录表单组件,并使用 useState 钩子维护表单的值。
首先,使用以下命令创建并启动一个 React 应用程序,
cd myapp
npm start
接下来,在组件文件夹(src/components/LoginForm.js)下创建一个 react 组件 LoginForm
import { useState } from 'react';
export default function LoginForm() {
// render code
}
接下来,使用 useState 钩子创建两个状态变量,用户名和密码,如下所示 -
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 是一个检查数据是可用还是空的函数。
接下来,呈现一个包含两个输入字段的登录表单,并使用状态变量(用户名和密码)、状态更新方法(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 使用 Hooks 返回的状态设置函数。
- 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 更新用户名只会更新 state 对象中的用户名并保留密码字段。
this.setState({
username: 'Peter'
})
在钩子中,setData(由 useState 返回的函数)将更新整个对象,如下所示 -
// create state
const [data, setDate] = useState({
username: 'John',
password: 'secret'
})
// update state - wrong
setData({
username: 'Peter'
})
更新的状态没有密码字段,如下所示 -
{
username: 'Peter'
}
为了解决这个问题,我们可以在javascript中使用spread运算符,如下所示 -
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 在对象(数据)中维护。
- setData 由 useState 钩子返回,并用作状态更新函数。
- data.* 语法用于获取状态的详细信息。
- …data 扩展运算符与 setData 函数一起使用以更新状态。
总结
useState hook 是在函数组件中进行状态管理的简单易行的方法。useState 可用于处理状态中的单个值或多个值。它既支持基本数据类型,也支持复杂对象。它允许多种状态设置功能(set*)和内部批处理,以简化流程。由于 useState 钩子的引入,函数组件终于得到了改进,可以做任何功能(从无状态到有状态)。