一、场景题:设计一个实时搜索输入框,说明选择依据
受控组件 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>
);
}
选择依据
-
实时反馈需求 :
• 输入内容需要立即触发搜索逻辑(防抖优化避免频繁请求)。
• 受控组件的
onChange
可精准捕获每次输入变化,适合高频交互。 -
状态同步性 :
• 搜索结果的渲染依赖当前输入值(如
query
清空时需同步清空结果)。• 受控组件通过
useState
保证UI与状态严格同步。 -
React 18优化 :
• 自动批处理(Automatic Batching)合并多次
setQuery
导致的渲染,减少性能损耗。•
useTransition
可标记搜索为低优先级更新,避免输入卡顿。
为何不选非受控组件?
-
延迟问题 :
• 非受控组件需通过
ref.current.value
手动获取值,无法实时响应输入变化。 -
防抖实现复杂 :
• 需自行监听
input
事件并添加定时器,代码冗余易出错。 -
状态追溯困难 :
• 清空输入框时需手动操作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>
);
}
核心特点:
- 直接DOM操作 :通过
inputRef.current.value
直接读写输入框值 - 无状态管理 :无需
useState
控制输入内容 - 适用场景:表单提交后只需最终值,无需实时验证或中间状态
对比受控组件优势:
• 更少渲染 :输入过程不会触发组件重渲染
• 代码更简:适合简单表单(如一次性文件上传)