第二节:React 基础篇-受控组件 vs 非受控组件

一、场景题:设计一个实时搜索输入框,说明选择依据

受控组件 vs 非受控组件

核心区别
特征 受控组件 非受控组件
数据管理 由React状态(state)控制 通过DOM元素(ref)直接访问
更新时机 每次输入触发onChange 提交时通过ref获取值
实时性 即时响应输入 延迟获取最终值
典型场景 需实时验证/反馈的输入 表单提交后处理

实时搜索输入框设计

场景需求

• 用户输入时立即触发搜索请求(需防抖优化)

• 输入内容需要动态高亮匹配结果

• 支持清空输入后重置搜索结果

方案选择:受控组件

代码实现

jsx 复制代码
import { useState, useEffect } from 'react';

function SearchInput() {
  const [query, setQuery] = useState('');
  const [results, setResults] = useState([]);

  // 防抖处理(300ms延迟)
  useEffect(() => {
    const handler = setTimeout(() => {
      if (query) {
        fetchResults(query).then(setResults);
      } else {
        setResults([]);
      }
    }, 300);

    return () => clearTimeout(handler);
  }, [query]);

  return (
    <div>
      <input
        type="text"
        value={query}
        onChange={(e) => setQuery(e.target.value)}
        placeholder="Search..."
      />
      <ul>
        {results.map((result) => (
          <li key={result.id}>{result.text}</li>
        ))}
      </ul>
    </div>
  );
}
选择依据
  1. 实时反馈需求

    • 输入内容需要立即触发搜索逻辑(防抖优化避免频繁请求)。

    • 受控组件的onChange可精准捕获每次输入变化,适合高频交互。

  2. 状态同步性

    • 搜索结果的渲染依赖当前输入值(如query清空时需同步清空结果)。

    • 受控组件通过useState保证UI与状态严格同步。

  3. React 18优化

    • 自动批处理(Automatic Batching)合并多次setQuery导致的渲染,减少性能损耗。

    useTransition可标记搜索为低优先级更新,避免输入卡顿。


为何不选非受控组件?

  1. 延迟问题

    • 非受控组件需通过ref.current.value手动获取值,无法实时响应输入变化。

  2. 防抖实现复杂

    • 需自行监听input事件并添加定时器,代码冗余易出错。

  3. 状态追溯困难

    • 清空输入框时需手动操作DOM(如ref.current.value = ""),违背React数据流原则。


总结

优先受控组件 :实时交互、状态依赖型场景(搜索、表单验证)。

选非受控组件 :仅需最终结果的文件上传、大型表单性能优化(如1000+字段)。

React 18+优化 :利用useDeferredValue进一步降低高频输入的性能开销:

jsx 复制代码
const deferredQuery = useDeferredValue(query); // 延迟更新派生值

二、场景:自己实现一个非受控组件的案例

以下是一个简单的非受控组件 实现案例,通过 ref 直接访问输入框的值:

jsx 复制代码
import { useRef } from 'react';

function UncontrolledInput() {
  // 1. 创建ref引用
  const inputRef = useRef(null);

  // 2. 提交时获取值
  const handleSubmit = (e) => {
    e.preventDefault();
    alert("输入的值: " + inputRef.current.value);
    inputRef.current.value = ""; // 直接操作DOM清空输入
  };

  return (
    <form onSubmit={handleSubmit}>
      <input 
        type="text" 
        ref={inputRef}  // 3. ref绑定到input
        placeholder="非受控输入" 
      />
      <button type="submit">提交</button>
    </form>
  );
}
核心特点:
  1. 直接DOM操作 :通过 inputRef.current.value 直接读写输入框值
  2. 无状态管理 :无需 useState 控制输入内容
  3. 适用场景:表单提交后只需最终值,无需实时验证或中间状态
对比受控组件优势:

更少渲染 :输入过程不会触发组件重渲染

代码更简:适合简单表单(如一次性文件上传)

相关推荐
恋猫de小郭14 分钟前
Flutter Zero 是什么?它的出现有什么意义?为什么你需要了解下?
android·前端·flutter
崔庆才丨静觅7 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60617 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了8 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅8 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅8 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅8 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment9 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅9 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊9 小时前
jwt介绍
前端