面试题:如何使用 React 的 useState?请举例说明

useState 是 React Hooks 中最基础也是最常用的 Hook,它允许你在函数组件中添加本地状态(state),而无需使用类组件。


1. 基本语法

const [state, setState] = useState(initialState);
  • state: 当前的状态值。
  • setState: 一个函数,用于更新状态。调用它会导致组件重新渲染。
  • initialState: 状态的初始值。可以是任何值(数字、字符串、对象、数组等)。

2. 基本使用示例

示例 1:计数器(数字状态)

import React, { useState } from 'react';

function Counter() {
  // 声明一个名为 "count" 的 state 变量,初始值为 0
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>你点击了 {count} 次</p>
      {/* 点击按钮时调用 setCount,将 count 加 1 */}
      <button onClick={() => setCount(count + 1)}>
        点我增加
      </button>
      
      {/* 另一种写法:传入一个函数,接收前一个状态值 */}
      <button onClick={() => setCount(prevCount => prevCount + 1)}>
        用函数形式增加
      </button>
    </div>
  );
}

示例 2:开关(布尔值状态)

function Toggle() {
  const [isOn, setIsOn] = useState(false);

  return (
    <div>
      {/* 根据 isOn 的值显示不同的文本和样式 */}
      <div className={`toggle ${isOn ? 'on' : 'off'}`}>
        {isOn ? 'ON' : 'OFF'}
      </div>
      <button onClick={() => setIsOn(!isOn)}>
        切换
      </button>
    </div>
  );
}

示例 3:输入框(字符串状态)

function NameInput() {
  const [name, setName] = useState('');

  return (
    <div>
      <input
        type="text"
        value={name} // 受控组件:value 由 state 控制
        onChange={(e) => setName(e.target.value)} // 更新 state
        placeholder="请输入你的名字"
      />
      <p>你好, {name || '陌生人'}!</p>
    </div>
  );
}

3. 使用对象或数组作为状态

当状态是一个对象或数组时,必须注意不可变性(Immutability)。不要直接修改状态,而是创建一个新对象/数组。

示例 4:用户信息(对象状态)

function UserProfile() {
  const [user, setUser] = useState({
    name: '',
    age: 0,
    email: ''
  });

  const handleChange = (e) => {
    const { name, value } = e.target;
    // ✅ 正确:创建新对象,使用展开操作符
    setUser(prevUser => ({
      ...prevUser,
      [name]: value
    }));
  };

  return (
    <form>
      <input
        name="name"
        value={user.name}
        onChange={handleChange}
        placeholder="姓名"
      />
      <input
        name="age"
        type="number"
        value={user.age}
        onChange={handleChange}
        placeholder="年龄"
      />
      <input
        name="email"
        value={user.email}
        onChange={handleChange}
        placeholder="邮箱"
      />
      <pre>{JSON.stringify(user, null, 2)}</pre>
    </form>
  );
}

示例 5:待办事项列表(数组状态)

function TodoList() {
  const [todos, setTodos] = useState([]);
  const [input, setInput] = useState('');

  const addTodo = () => {
    if (input.trim() !== '') {
      // ✅ 正确:创建新数组,使用展开操作符
      setTodos(prevTodos => [
        ...prevTodos,
        { id: Date.now(), text: input, completed: false }
      ]);
      setInput(''); // 清空输入框
    }
  };

  const toggleTodo = (id) => {
    setTodos(prevTodos =>
      prevTodos.map(todo =>
        todo.id === id ? { ...todo, completed: !todo.completed } : todo
      )
    );
  };

  return (
    <div>
      <input
        value={input}
        onChange={(e) => setInput(e.target.value)}
        onKeyPress={(e) => e.key === 'Enter' && addTodo()}
        placeholder="添加新任务"
      />
      <button onClick={addTodo}>添加</button>
      <ul>
        {todos.map(todo => (
          <li 
            key={todo.id} 
            style={{ textDecoration: todo.completed ? 'line-through' : 'none' }}
            onClick={() => toggleTodo(todo.id)}
          >
            {todo.text}
          </li>
        ))}
      </ul>
    </div>
  );
}

4. useState 的重要特性

特性说明
惰性初始化如果初始状态是通过复杂计算得到的,可以传入一个函数:useState(() => computeExpensiveValue())。该函数只在首次渲染时执行。
函数式更新当新状态依赖于前一个状态时,使用 setState(prevState => newState) 形式,可以避免闭包问题。
批量更新在事件处理函数中,多次 setState 调用可能会被合并(批处理),以提高性能。
触发重新渲染每次调用 setState,即使新旧值相等(对于基础类型),也会触发组件重新渲染(但 React 会对虚拟 DOM 进行优化)。

总结

useState 是 React 函数组件的“状态引擎”:

  1. 声明状态:使用 const [state, setState] = useState(initialValue)
  2. 读取状态:直接使用 state 变量。
  3. 更新状态:调用 setState(newValue)setState(prev => newValue)
  4. 遵守不可变性:更新对象或数组时,创建新实例,不要直接修改。

它是构建交互式 React 应用的基础,结合 useEffect 等其他 Hooks,可以实现类组件的所有功能,且代码通常更简洁、更易于理解。

THE END
喜欢就支持一下吧
点赞8 分享