useState 是 React 提供的核心 Hook,专门用于在函数组件中添加和管理状态(State),让函数组件能像类组件一样拥有自己的状态,是 React 开发中最常用的 Hook 之一。
一、核心作用
- 为函数组件添加响应式状态:状态变化时,组件会自动重新渲染,UI 同步更新。
- 存储组件的动态数据:比如表单输入值、开关状态、列表数据、计数器数值等。
- 提供状态更新方法:通过指定的方法修改状态,而非直接赋值,保证状态更新的可追踪性。
二、基本用法
1. 引入与语法
首先需要从 react 中导入 useState,然后在函数组件内部调用它,语法如下:
import { useState } from 'react';
function 组件名() {
// 语法:const [状态名, 更新状态的方法名] = useState(初始值);
const [state, setState] = useState(initialState);
// 组件逻辑...
return UI结构;
}
2. 关键说明
- 返回值:
useState会返回一个数组,包含两个元素:- 第一个是当前状态值(读取状态时直接使用);
- 第二个是更新状态的函数(修改状态时调用,传入新值即可)。
- 初始值:
initialState是状态的初始值,支持任意数据类型(数字、字符串、布尔值、对象、数组、函数等)。 - 调用时机:
useState必须在函数组件的顶层调用,不能在循环、条件判断或嵌套函数中调用(遵循 React Hook 规则)。
三、实用示例
示例 1:基础计数器(简单类型状态)
import { useState } from 'react';
function Counter() {
// 定义状态:count 初始值为 0,setCount 是更新 count 的方法
const [count, setCount] = useState(0);
return (
<div>
<p>当前计数:{count}</p>
{/* 点击按钮更新状态:直接传入新值 */}
<button onClick={() => setCount(count + 1)}>增加</button>
<button onClick={() => setCount(count - 1)}>减少</button>
<button onClick={() => setCount(0)}>重置</button>
</div>
);
}
示例 2:表单输入(对象类型状态)
当状态是对象/数组时,更新时需要返回新的对象/数组(React 状态是不可变的,不能直接修改原对象):
import { useState } from 'react';
function Form() {
// 初始状态是对象,包含用户名和密码
const [formData, setFormData] = useState({
username: '',
password: ''
});
// 处理输入变化:使用展开运算符保留原有属性,只更新对应字段
const handleChange = (e) => {
const { name, value } = e.target;
setFormData({
...formData, // 保留原有的其他字段
[name]: value // 动态更新当前输入的字段
});
};
return (
<div>
<input
type="text"
name="username"
value={formData.username}
onChange={handleChange}
placeholder="用户名"
/>
<input
type="password"
name="password"
value={formData.password}
onChange={handleChange}
placeholder="密码"
/>
<p>用户名:{formData.username}</p>
<p>密码:{formData.password}</p>
</div>
);
}
示例 3:函数式更新(依赖前一次状态)
当新状态依赖于前一次的状态值时,推荐使用函数式更新,避免因异步更新导致的状态错误:
import { useState } from 'react';
function AsyncCounter() {
const [count, setCount] = useState(0);
// 点击一次,连续增加 2(依赖前一次状态,用函数式更新更安全)
const handleAdd = () => {
setCount(prevCount => prevCount + 1); // prevCount 是前一次的状态值
setCount(prevCount => prevCount + 1);
};
return (
<div>
<p>计数:{count}</p>
<button onClick={handleAdd}>增加 2</button>
</div>
);
}
四、核心特性
- 状态是独立的:每个组件实例的
useState状态都是独立的,互不干扰。 - 状态更新是异步的:调用
setState后,状态不会立即改变,组件会进入重新渲染队列,下次渲染时才能拿到最新状态。 - 状态是不可变的:不能直接修改状态(如
count++或formData.username = 'xxx'),必须通过setState传入新值/新对象/新数组。 - 初始值只执行一次:组件首次渲染时,
useState会使用初始值;后续重新渲染时,会忽略初始值,直接使用当前状态。 - 支持惰性初始值:如果初始值需要复杂计算(如函数执行结果),可以传入一个函数,该函数只在首次渲染时执行:
// 复杂计算的初始值,用函数惰性初始化,避免重复计算 const [count, setCount] = useState(() => { return 10 + 20; // 复杂计算逻辑 });
五、常见误区
- 直接修改状态:错误写法
count++、formData.username = 'test',正确写法是通过setState传入新值。 - 在条件/循环中调用 useState:违反 Hook 规则,会导致状态混乱,必须在组件顶层调用。
- 忽略状态异步更新:调用
setState后立即读取状态,拿到的还是旧值,需在下次渲染或useEffect中获取最新状态。 - 对象/数组状态直接修改:必须返回新的对象/数组(用展开运算符
...或map/filter等方法),否则 UI 不会更新。
总结
useState是函数组件管理状态的核心 Hook,通过[状态, 更新方法]的结构实现状态读写。- 支持任意数据类型的状态,更新对象/数组时需保证不可变性,依赖前序状态时用函数式更新。
- 遵循 Hook 规则(顶层调用),避免直接修改状态,就能高效实现组件的动态交互。
