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.jsxfunction UserContainer() {  const { data, isLoading } = useQuery('user', fetchUser);
  return <UserProfile user={data} loading={isLoading} />;}
// UserProfile.jsxfunction UserProfile({ user, loading }) {  if (loading) return <Skeleton />;  return <div>{user.name}</div>;}

实际收益

当你一致性地使用该模式时,组件会更具可组合性。你不再需要纠结 API 调用放在哪里,也能避免在条件渲染时写出嵌套很深的三元表达式。每个部分只做一件事 —— 并且做好。

2. Controlled vs Uncontrolled 模式

定义

  • Controlled 组件:父组件通过 props 管理 value。

  • Uncontrolled 组件:内部通过 ref 自行管理 state。

为什么有效

有时你需要灵活性。Controlled 组件适合集成到表单中,而 Uncontrolled 组件渲染更快,且更易上手。

// Controllede => setValue(e.target.value)} />
// Uncontrolled<input defaultValue="Hello" ref={inputRef} />

实际收益

清楚何时使用哪种方式能提升性能并简化表单。Controlled 组件功能强大,但会带来更多渲染。混合方式能让大型表单更顺畅。

3. Compound Component 模式

定义

通过共享 state 和 context 设计父子组件关系。父组件管理逻辑,并通过 context 而不是 props 向子组件传递控制权。

为什么有效

它避免了 prop drilling,并为用户提供了一种更声明式的 UI 组合方式。

<Tabs>  <Tabs.List>    <Tabs.Trigger value="posts">Posts</Tabs.Trigger>    <Tabs.Trigger value="comments">Comments</Tabs.Trigger>  </Tabs.List>  <Tabs.Panel value="posts">Post content</Tabs.Panel>  <Tabs.Panel value="comments">Comment content</Tabs.Panel></Tabs>


实际收益

Compound 组件让 API 更加优雅。消费者无需传递 ID 和 handler,只需组合接口即可。而在内部,你能保持 state 管理的集中化。它不仅改善功能,也提升了开发体验。

4. Render Props

定义

不再传递静态 JSX 子元素,而是传递一个返回 JSX 的函数 —— 这样可以访问内部逻辑。

为什么有效

它能暴露功能而不控制展示。可以把它看作是 hooks 的前身。

<Toggle>  {({ on, toggle }) => (    <button onClick={toggle}>{on ? 'ON' : 'OFF'}</button>  )}</Toggle>

实际收益

在 class 组件或共享 UI 逻辑场景下依然有用。虽然现在 hooks 更流行,但 Render Props 依然在嵌套或动态 UI 中提供了强大的组合模式。

5. Headless Component 模式

定义

将行为与展示分离。组件提供 state 和逻辑,但将渲染交给使用者。

为什么有效

这样你可以完全掌控标记、样式和布局,同时还能利用经过验证的逻辑,例如可访问性、ARIA role 和键盘交互。

<Dropdown>  {({ open, toggle }) => (    <button onClick={toggle}>      {open ? 'Close' : 'Open'}    </button>  )}</Dropdown>

实际收益

Headless 组件能帮助你构建灵活且框架无关的 UI 库。它们不会限制界面外观,而是让团队按需渲染,同时保持逻辑的集中与复用。

6. State Reducer 模式

定义

允许用户覆盖内部的 state 转换逻辑。组件内部使用 reducer,同时允许消费者注入自定义逻辑。

为什么有效

消费者无需 fork 或复制组件即可获得控制权。这类似于 state 更新的控制反转。

function useToggle({ reducer = defaultReducer } = {}) {  const [state, dispatch] = useReducer(reducer, { onfalse });
  const toggle = () => dispatch({ type'toggle' });  return [state.on, toggle];}

实际收益

非常适合设计系统和可复用 hooks。默认情况下提供灵活性,并让高级场景能插入自定义行为。这是“可复用”与“可配置”的差别。

7. Smart-Dumb Component 配对

定义

一种特定的角色划分方式:

  • Smart 组件:处理协调、数据获取、mutation、state 管理。

  • Dumb 组件:无状态,只负责展示和布局。

为什么有效

这种明确的角色区分避免了所有组件“啥都干”。它与软件工程中的单一职责原则完美契合。

// Smartfunction TodoListContainer() {  const todos = useTodos();  return <TodoList todos={todos} />;}
// Dumbfunction TodoList({ todos }) {  return (    <ul>      {todos.map(todo => <li key={todo.id}>{todo.text}</li>)}    </ul>  );}

实际收益

当 Dumb 组件纯粹且解耦时,它们可以直接放进 Storybook,单独测试,并跨功能复用。你会开始发现每个功能都能拆分为可复用的积木,代码库也会更轻量、更模块化。

8. 逻辑与 UI 的就近放置

定义

将 state 和逻辑尽可能靠近使用它们的组件,而不是过早抽象。

为什么有效

避免不必要的间接性。让组件自包含,更容易删除、重构或迁移。

与其这样:

// useFormState.jsexport function useFormState() {  ...}
// Form.jsxconst { fields, errors } = useFormState();

不如先这样:

function Form() {  const [fields, setFields] = useState({});  const [errors, setErrors] = useState({});  ...}

只有在确实需要复用时,再提取到 hook。

实际收益

过早的抽象会导致代码脆弱、过度设计。就近放置鼓励清晰与意图。

9. Props 配置 + Children 组合

定义

  • 使用 props 配置行为。

  • 使用 children 组合 UI。

为什么有效

保持 API 一致性。帮助他人理解哪些是可配置的,哪些是可组合的。

<Card variant="elevated">  <Card.Title>Settings</Card.Title>  <Card.Body>    <SettingsForm />  </Card.Body></Card>
  • variant 是配置 prop。

  • children 是插入布局的嵌套组件。

实际收益

这让组件像迷你 DSL(领域特定语言)。它以简洁、声明式的方式赋能使用者。组件变得直观且可组合。

结语

React 不会强制规则。这既是它的优势,也是它的陷阱。

我们不需要从零开始造轮子,也不必追随所有潮流。但当我们带着意图来设计组件 —— 使用这些架构模式时,就能构建出经得起时间考验的系统。

一个以清晰为基础的 UI 更容易测试、扩展,并帮助新成员快速上手。这些模式不是 hack,而是经过 React 化的永恒原则。

架构无需恐惧。我们可以理解它、掌握它,并在需要时用好它。


🔥号外~号外~

最近我们推出了大厂的一手面经模块,都是刚面完的小伙伴们热乎乎分享的:

  • 字节、阿里、腾讯最新面试真题
  • 面试流程和注意事项
  • 面试官的重点提问和考察点

这些面经都是花了不少心思整理的,比网上那些过时的八股文靠谱多了。

有需要的小伙伴可以点击这里👉前端面试题宝典打开小程序,首页即可直接领取【大厂真实面经】),也可直接联系小助理咨询。

毕竟信息差就是竞争力,早点了解面试套路,早点拿到心仪offer!

有会员购买、辅导咨询的小伙伴,可以通过下面的二维码,联系我们的小助手。

图片