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 Hooks 进行状态管理 ReactJS Hooks 的组件生命周期 ReactJS 布局组件 ReactJS 分页 ReactJS Material UI ReactJS Http 客户端编程 ReactJS 表单编程 ReactJS 受控组件 ReactJS 非受控组件 ReactJS Formik ReactJS 条件渲染 ReactJS 列表 ReactJS Key 键 ReactJS 路由 ReactJS Redux ReactJS 动画 ReactJS Bootstrap ReactJS Map 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 Portals ReactJS 不使用 ES6 ECMAScript ReactJS 不使用 JSX 的 React ReactJS Reconciliation ReactJS Refs 和 DOM ReactJS 渲染道具 ReactJS 静态类型检查 ReactJS 严格模式 ReactJS Web 组件

其他概念

ReactJS 日期选择器 ReactJS Helmet ReactJS 内联样式 ReactJS PropTypes ReactJS BrowserRouter ReactJS DOM ReactJS 轮播 ReactJS 图标 ReactJS 表单组件 ReactJS 参考 API

ReactJS 有用资源

ReactJS 快速指南 ReactJS 备忘录 Axios 备忘录 ReactJS 有用资源 ReactJS 讨论


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;

接下来,打开浏览器并检查应用程序。应用程序将使用状态变量收集用户输入的数据,并使用验证函数对其进行验证。如果用户输入了正确的数据,它将显示如下所示的数据 −

Applying State Hook

否则,它将抛出如下所示的错误 −

Applying State Hook

对象作为状态

在基于类的状态管理中,setState 方法支持状态对象的部分更新。例如,让我们考虑将登录表单数据作为对象保存在状态中。

Applying State Hook
{
   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(钩子),函数组件最终被改进为可以执行任何功能(从无状态到有状态)。