React 组件设计:9 种让你的 UI 坚不可摧的架构模式
原文地址:https://medium.com/@hritvikom/react-component-design-9-architecture-patterns-that-make-your-ui-bulletproof-eb4fb14dfe28
原文作者: Scripting Soul
引言
React 给予了你极大的自由。但自由也会带来不一致、面条代码和团队协作的混乱 —— 除非你使用可扩展的设计模式。
本文将深入介绍 9 种经过打磨和验证的架构模式,它们会改变你设计组件的方式。这些不是 hack,而是基本功。无论你在构建仪表盘、设计系统还是数据密集型应用,它们都适用。
这些模式将会:
-
让你的组件更易维护
-
鼓励在不过度设计的前提下实现复用
-
简化大型团队中的协作
1. Presentational + Container 模式
定义
将组件拆分为两类:
-
Container:处理数据获取、state 和逻辑。
-
Presenter:只负责展示。
为什么有效
它能让逻辑与 UI 清晰分离。Presenter 是“哑组件”(无副作用、无 state),因此它可复用、可测试、可预测。Container 可以独立演进,而不会影响 UI 的样式或结构。
// UserContainer.jsxfunctionUserContainer() {const { data, isLoading } = useQuery('user', fetchUser);
return<UserProfileuser={data}loading={isLoading} />;}
// UserProfile.jsxfunctionUserProfile({ user, loading }) {if (loading) return<Skeleton />;return<div>{user.name}</div>;}
实际收益
当你一致性地使用该模式时,组件会更具可组合性。你不再需要纠结 API 调用放在哪里,也能避免在条件渲染时写出嵌套很深的三元表达式。每个部分只做一件事 —— 并且做好。
2. Controlled vs Uncontrolled 模式
定义
-
Controlled 组件:父组件通过 props 管理 value。
-
Uncontrolled 组件:内部通过 ref 自行管理 state。
为什么有效
有时你需要灵活性。Controlled 组件适合集成到表单中,而 Uncontrolled 组件渲染更快,且更易上手。
// Controlled<input value={value} onChange={e =>setValue(e.target.value)} />
// Uncontrolled<inputdefaultValue="Hello"ref={inputRef} />
实际收益
清楚何时使用哪种方式能提升性能并简化表单。Controlled 组件功能强大,但会带来更多渲染。混合方式能让大型表单更顺畅。
3. Compound Component 模式
定义
通过共享 state 和 context 设计父子组件关系。父组件管理逻辑,并通过 context 而不是 props 向子组件传递控制权。
为什么有效
它避免了 prop drilling,并为用户提供了一种更声明式的 UI 组合方式。
<Tabs><Tabs.List><Tabs.Triggervalue="posts">Posts</Tabs.Trigger><Tabs.Triggervalue="comments">Comments</Tabs.Trigger></Tabs.List><Tabs.Panelvalue="posts">Post content</Tabs.Panel><Tabs.Panelvalue="comments">Comment content</Tabs.Panel></Tabs>
实际收益
Compound 组件让 API 更加优雅。消费者无需传递 ID 和 handler,只需组合接口即可。而在内部,你能保持 state 管理的集中化。它不仅改善功能,也提升了开发体验。
4. Render Props
定义
不再传递静态 JSX 子元素,而是传递一个返回 JSX 的函数 —— 这样可以访问内部逻辑。
为什么有效
它能暴露功能而不控制展示。可以把它看作是 hooks 的前身。
<Toggle> {({ on, toggle }) => (<buttononClick={toggle}>{on ? 'ON' : 'OFF'}</button> )}</Toggle>
实际收益
在 class 组件或共享 UI 逻辑场景下依然有用。虽然现在 hooks 更流行,但 Render Props 依然在嵌套或动态 UI 中提供了强大的组合模式。
5. Headless Component 模式
定义
将行为与展示分离。组件提供 state 和逻辑,但将渲染交给使用者。
为什么有效
这样你可以完全掌控标记、样式和布局,同时还能利用经过验证的逻辑,例如可访问性、ARIA role 和键盘交互。
<Dropdown> {({ open, toggle }) => (<buttononClick={toggle}> {open ? 'Close' : 'Open'}</button> )}</Dropdown>
实际收益
Headless 组件能帮助你构建灵活且框架无关的 UI 库。它们不会限制界面外观,而是让团队按需渲染,同时保持逻辑的集中与复用。
6. State Reducer 模式
定义
允许用户覆盖内部的 state 转换逻辑。组件内部使用 reducer,同时允许消费者注入自定义逻辑。
为什么有效
消费者无需 fork 或复制组件即可获得控制权。这类似于 state 更新的控制反转。
functionuseToggle({ reducer = defaultReducer } = {}) {const [state, dispatch] = useReducer(reducer, { on: false });
consttoggle = () => dispatch({ type: 'toggle' });return [state.on, toggle];}
实际收益
非常适合设计系统和可复用 hooks。默认情况下提供灵活性,并让高级场景能插入自定义行为。这是“可复用”与“可配置”的差别。
7. Smart-Dumb Component 配对
定义
一种特定的角色划分方式:
-
Smart 组件:处理协调、数据获取、mutation、state 管理。
-
Dumb 组件:无状态,只负责展示和布局。
为什么有效
这种明确的角色区分避免了所有组件“啥都干”。它与软件工程中的单一职责原则完美契合。
// SmartfunctionTodoListContainer() {const todos = useTodos();return<TodoListtodos={todos} />;}
// DumbfunctionTodoList({ todos }) {return (<ul> {todos.map(todo => <likey={todo.id}>{todo.text}</li>)}</ul> );}
实际收益
当 Dumb 组件纯粹且解耦时,它们可以直接放进 Storybook,单独测试,并跨功能复用。你会开始发现每个功能都能拆分为可复用的积木,代码库也会更轻量、更模块化。
8. 逻辑与 UI 的就近放置
定义
将 state 和逻辑尽可能靠近使用它们的组件,而不是过早抽象。
为什么有效
避免不必要的间接性。让组件自包含,更容易删除、重构或迁移。
与其这样:
// useFormState.jsexportfunctionuseFormState() { ...}
// Form.jsxconst { fields, errors } = useFormState();
不如先这样:
functionForm() {const [fields, setFields] = useState({});const [errors, setErrors] = useState({}); ...}
只有在确实需要复用时,再提取到 hook。
实际收益
过早的抽象会导致代码脆弱、过度设计。就近放置鼓励清晰与意图。
9. Props 配置 + Children 组合
定义
-
使用 props 配置行为。
-
使用 children 组合 UI。
为什么有效
保持 API 一致性。帮助他人理解哪些是可配置的,哪些是可组合的。
<Cardvariant="elevated"><Card.Title>Settings</Card.Title><Card.Body><SettingsForm /></Card.Body></Card>
-
variant 是配置 prop。
-
children 是插入布局的嵌套组件。
实际收益
这让组件像迷你 DSL(领域特定语言)。它以简洁、声明式的方式赋能使用者。组件变得直观且可组合。
结语
React 不会强制规则。这既是它的优势,也是它的陷阱。
我们不需要从零开始造轮子,也不必追随所有潮流。但当我们带着意图来设计组件 —— 使用这些架构模式时,就能构建出经得起时间考验的系统。
一个以清晰为基础的 UI 更容易测试、扩展,并帮助新成员快速上手。这些模式不是 hack,而是经过 React 化的永恒原则。
架构无需恐惧。我们可以理解它、掌握它,并在需要时用好它。
更多推荐



所有评论(0)