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 是用于检查数据是否可用或为空的函数。

接下来,呈现一个包含两个输入字段的登录表单,并使用状态变量(usernamepassword)、状态更新方法(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(钩子),函数组件最终被改进为可以执行任何功能(从无状态到有状态)。