悠悠楠杉
网站页面
正文:
在React开发中,受控组件(Controlled Components)是处理表单数据的标准模式,但当遇到动态列表场景时,开发者常会遇到一个棘手问题:状态更新了,但UI却没有同步渲染。这种不一致性可能导致用户输入丢失、界面错乱甚至数据提交错误。
当动态渲染一组受控输入框时,React依赖key属性来识别列表项的变更。如果key设计不当(例如使用数组索引),删除或排序操作会导致React误判DOM节点关系。更隐蔽的问题是:直接修改状态数组而非创建新引用,使得React的浅比较机制失效。
以下是一个包含增删改查的完整解决方案:
function DynamicList() {
const [items, setItems] = useState([
{ id: uuid(), text: '' }
]);
// 始终创建新数组保证引用变化
const handleChange = (id, newText) => {
setItems(prev => prev.map(item =>
item.id === id ? { ...item, text: newText } : item
));
};
// 使用唯一ID作为key
const handleAdd = () => {
setItems(prev => [...prev, { id: uuid(), text: '' }]);
};
// 过滤时返回全新数组
const handleDelete = (id) => {
setItems(prev => prev.filter(item => item.id !== id));
};
return (
<div>
{items.map((item) => (
<div key={item.id}>
<input
value={item.text}
onChange={(e) => handleChange(item.id, e.target.value)}
/>
<button onClick={() => handleDelete(item.id)}>删除</button>
</div>
))}
<button onClick={handleAdd}>新增条目</button>
</div>
);
}useReducer替代多次setState,避免频繁触发重渲染。React的状态不可变性(Immutability)原则在这个场景中尤为关键。开发者必须像对待函数式编程中的纯函数一样对待状态更新——永远返回新数据,绝不修改原有对象。这种思维模式能从根本上避免90%的UI同步问题。
通过将每个列表项视为独立受控单元、严格管理状态生命周期、合理运用React的协调(Reconciliation)机制,可以构建出稳定可靠的动态表单系统。记住,在React的世界里,正确的数据流必然带来正确的UI表现。