- 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,函数组件最终得到了改进,可以执行任何功能(从无状态到有状态)。