组件是否应该访问数据源?
组件是否应该访问数据源?
在 react 早期,redux 刚刚开始流行的时候,通常组件会分别存在 container
和 component
文件夹下。
在 container
我们会访问 api、redux 或 localstorage 等外部数据源,而 component
只能接受 props
参数。
但是到了今天,zustand、Jotai 等原子化设计的状态管理库、swr 这种利用 hooks 封装请求的库大行其道。项目中没有了 container
,大家都非常随意的在 component
里面访问接口、全局变量、zustand store、redux 等等。
这点到底好还是不好呢?
历史背景与技术约束
首先我们要知道早期没有 hooks 的时候,React 接入 redux 是需要使用 hoc 的。Redux 有自己的强约束性:要求通过 connect
高阶组件接入 store。
自然形成了容器组件作为“中间层”的架构。
技术演进带来的范式转变
在 react 16.8 之后,函数组件和 hooks 成为主流,useState/useEffect 等 API 模糊了组件层级边界。
这种背景下,redux 也不需要 connect
高阶组件了,直接 useDispatch
useSelector
就可以在组件中使用,后面也衍生出 Zustand/Jotai 等更方便简单的全局数据管理库。
甚至于还有 swr
这种项目,让我们能直接在多个组件中直接调用 useUser
,它内部会自动帮我们处理——不管在多少组件中都用了 useUser
,都只会进行一次请求。相当于直接同时解决了全局状态管理、请求结果缓存、请求去重等多个问题。
现代实践的利弊分析
✅ 优势:
- 开发体验提升:减少文件跳转,逻辑更内聚
- 更灵活的代码组织:逻辑与 UI 可以按功能而非类型组织
- 更适合现代 SSR/SSG:数据获取与组件更紧密集成
❌ 风险: 4. 组件熵增:单个组件可能混杂 UI/逻辑/副作用 5. 测试复杂度:需要更多 mock 和集成测试 6. 可重用性下降:业务耦合度高的组件难以复用 7. 追踪困难:数据流在组件树中更分散
架构选择的平衡之道
小型项目:允许在组件内直接访问状态
1 |
|
大型项目:显式分层依然必要
1 |
|
现代最佳实践建议
- 逻辑收敛原则:即使不显式分层,也要通过自定义 Hooks 收敛副作用
- 组件纯度分级:
- Level 1: 纯 UI 组件 (禁止任何外部访问)
- Level 2: 轻度业务组件 (允许访问上下文)
- Level 3: 业务容器组件 (允许完整副作用)
- 架构守护方案:
- 通过 ESLint 规则限制某些目录下的组件不能直接访问 store
- 使用分层测试策略(单元测试/集成测试/E2E 测试的比例分配)
总结来看,行业惯例的转变本质是开发效率与架构严谨性的动态平衡。关键不在于是否使用 container/component 模式,而是能否建立适合当前团队和项目阶段的约束规则。对于追求长期维护性的项目,建议保留某种形式的分层约定,但实现方式可以更现代化(如通过 Hooks 分层而非文件类型分层)。