
本文介绍如何将硬编码的复选框列表重构为高内聚、低耦合的可复用 react 组件,通过分离数据源、状态管理与 ui 渲染,提升可读性、可测试性与动态扩展能力。
本文介绍如何将硬编码的复选框列表重构为高内聚、低耦合的可复用 react 组件,通过分离数据源、状态管理与 ui 渲染,提升可读性、可测试性与动态扩展能力。
在 React 开发中,面对一组功能相似的复选框(如设置项、筛选条件或权限配置),若采用直接罗列 的方式,不仅违反 DRY(Don’t Repeat Yourself)原则,更会导致状态逻辑分散、难以维护和动态响应。原始写法虽简洁,却缺乏数据驱动意识;而初版重构虽引入了对象状态,仍将描述文本与勾选状态耦合在同一个数据结构中,导致状态更新冗余、渲染逻辑紧耦合、且难以支持运行时动态变更列表项。
更优解是职责分离:
- ✅ items —— 仅定义静态元数据(id, label),与业务语义强相关,可来自 API、配置或常量;
- ✅ checkedIds —— 纯粹的状态映射({ item1: true, item3: false }),轻量、扁平、易序列化;
- ✅ CheckboxGroup —— 无状态函数组件,专注渲染与事件委派,完全受控于外部传入的 items 和 checkedIds;
- ✅ onChange 回调 —— 由父组件提供,保证状态更新逻辑集中可控,便于添加副作用(如日志、联动校验等)。
以下为推荐实现:
// CheckboxGroup.jsx —— 可复用、可测试、无副作用
function CheckboxGroup({ items, checkedIds, onChange }) {
return (
<div classname="checkbox-group">
{items.map(({ id, label }) => (
<label key="{id}" classname="checkbox-label">
<input type="checkbox" name="{id}" checked undefined onchange="{(e)"> onChange(id, e.target.checked)}
/>
<span>{label}</span>
</label>
))}
</div>
);
}
// App.jsx —— 状态管理与业务逻辑所在
import React, { useState } from 'react';
const baseItems = Array.from({ length: 5 }, (_, i) => ({
id: `item${i + 1}`,
label: `#${i + 1} description`
}));
export default function App() {
const [checkedIds, setCheckedIds] = useState({});
const handleChange = (id, checked) =>
setCheckedIds(prev => ({ ...prev, [id]: checked }));
// ✨ 动态能力示例:当勾选数 ≥ 3 时,自动转为大写标签
const numberChecked = Object.values(checkedIds).filter(Boolean).length;
const items = numberChecked >= 3
? baseItems.map(item => ({ ...item, label: item.label.toUpperCase() }))
: baseItems;
return (
<div classname="App">
<h2>动态复选框组</h2>
<checkboxgroup items="{items}" checkedids="{checkedIds}" onchange="{handleChange}"></checkboxgroup><p>当前已勾选:<strong>{numberChecked}</strong> 项</p>
<pre class="brush:php;toolbar:false;">{JSON.stringify(checkedIds, null, 2)}










